Sunday, December 14, 2025

Java notes2

 Java 8 features

1. Lambda expression

 

2. Method References

    - It is an alternative to Lambda expr

    - Also used to access the method of functional interface, instead of writing logic separately using lambda expr we can refer to the methods that already exists

    - When signature of interface method matches with static method or instance method or constructor

    - Denoted by ::

 

3 types

1. Reference to static method

2. Reference to instance method

 

interface MyInterface{

              void show();

}

 

public class Main {

              /*public static void add() {

                             System.out.println("Reference to static method");

              }*/

             

              public void sum() {

                             System.out.println("Reference to instance method");

              }

              public static void main(String...args) {

                  MyInterface m1=()->System.out.println("Using Lambda");

                  m1.show();  //Using Lambda

                 

                  //MyInterface m2=Main::add;

                 // m2.show();  //Reference to static method

                 

                  Main m3=new Main();

                  MyInterface m4=m3::sum;

                  m4.show(); //Reference to instance method

                                          

    }

}

 

3. Reference to constructor

 

interface MyInterface{

              //Main show();

              Main show(String s);

}

 

public class Main {

              Main() {

                             System.out.println("Reference to default constructor");

              }

              Main(String s) {

                             System.out.println("Reference to constructor: "+s);

              }

              public static void main(String...args) {

                // MyInterface m1=Main::new;

                // m1.show();  //Reference to default constructor

                            

                             MyInterface m1=Main::new;

                             m1.show("Hello");  //Reference to constructor: Hello

    }

}

 

 

Predefined Functional Interface

     - present in java.util.function.* package

 

1. Consumer interface

     void accept(T t);

 

From JDK1.8 List and Set interface introduced a method called void forEach(Consumer c) - used to iterate elts of List and Set interface individually

 

2. BiConsumer interface

     void accept(T t, U u);     

 

From JDK1.8 Map interface introduced a method called void forEach(BiConsumer c) - used to iterate elts of Map interface individually

 

3. Function interface

      R apply(T t)

 

4. BiFunction interface

      R apply(T t, U u)

 

5. Predicate interface

      boolean test(T t)

 

6. BiPredicate interface

      boolean test(T t, U u)

 

7. Supplier interface

      T get()

 

8. BooleanSupplier interface

      boolean getAsBoolean()

 

9. UnaryOperator interface extends Function interface

      R apply(T t)

 

10. BinaryOperator interface extends BiFunction interface

      R apply(T t, U u)

 

public class Main {

              public static void main(String...args) {

                 List<String> l1=new ArrayList<>();

                 l1.add("Ram");

                 l1.add("Sam");

                 l1.add("Tam");

                 l1.add("Jam");

                 System.out.println(l1); //[Ram,Sam,Tam,Jam]

                // l1.forEach((e)->System.out.println(e));  //lambda expr

                 l1.forEach(System.out::println);  //reference to instance method

                

                 Map<Integer,String> hm=new HashMap<>();

                 hm.put(20, "Ram");

                 hm.put(10, "Sam");

                 hm.put(30, "Jam");

                 hm.put(40, "Tam");

                 System.out.println(hm); //{20=Ram, 40=Tam, 10=Sam, 30=Jam}

                

                 hm.forEach((k,v)->System.out.println("Key: "+k+" Value: "+v));

                

                 Function<String,Integer> f1=(s)->s.length();

                 System.out.println(f1.apply("hello"));  //5

                

                 BiFunction<Integer,Integer,Integer> bf=(x1,y1)->x1+y1;

                 System.out.println(bf.apply(10,20));  //30

                

                 Predicate<String> p=(p1)->p1.startsWith("Foo");

                 System.out.println(p.test("Foobar")); //true

                

                 BiPredicate<Integer,String> bp=(a1,a2)->a1>10 & a2.endsWith("Bar");

                 System.out.println(bp.test(25, "Foobar")); //true

                

                 Supplier<String> su=()->"hello";

                 System.out.println(su.get()); //hello

                

                 BooleanSupplier bp1=()->10>20;

                 System.out.println(bp1.getAsBoolean()); //false

                

                 BiFunction<Integer,String,Boolean> bf1=(x1,y1)->x1>10 & y1.startsWith("Foo");

                 System.out.println(bf1.apply(20,"Foobar")); //true

                

                 BinaryOperator<String> bo=(s1,s2)->s1.concat(s2);

                 System.out.println(bo.apply("Hello", "world"));

    }

}

 

Streams API

   - used to process collection of objects with less number of coding

   - fetch collection of objects from some source(ie) List or Set or Array and process them sequentially

   - Collection framework also stores collection of objects and we can manipulate and process the object, but with streams api we can only process the collection of object and we cant manipulate it

   - present in java.util.streams.* package

   - 2 types - finite(fixed value) and infinite(unlimited value) streams

   - 2 types of operation

1. Intermediate operation - return stream itself - optional - we can chain multiple intermediate operation at the same time

   - filter(), map(), flatMap(), sorted(), peek(), skip(), limit(), distinct(), dropWhile(), takeWhile()

2. Terminal operation - It will traverse into newly generated streams and returns a single value - mandatory - we cant chain multiple terminal operation

   - toArray(), forEach(), count(), min(), max(), reduce(), collect(), anyMatch(), allMatch(), noneMatch(), findFirst()

 

3 steps

Creation of stream - Intermediate operation - Terminal operation

   - If we perform terminal operation then that stream is completely closed, so when we perform any other operation on closed stream then we get IllegalStateException

 

 

1. Creation of Stream(Finite stream) - 2 ways

1. stream() - used to create a stream from some source like List or Set or Array

 

String[] a=new String[]{"one","two","three"};   //Anonmyous array

Stream<String> st1=a.stream();

 

List<Integer> l=new ArrayList<>();

l.add(1);

l.add(2);

l.add(3);

l.add(4);

Stream<Integer> st2=l.stream();

 

2. of() - used to create our own stream

 

Stream<String> st3=Stream.of("one","two","three");

 

 

anyMatch(Predicate), allMatch(Predicate), noneMatch(Predicate) - terminal

 

filter(Predicate) - intermediate - used to filter data based on some condition

 

reduce() - terminal - used to reduce multiple value into single value

   - Optional reduce(BinaryOperator)

   - Integer reduce(int initialvalue,BinaryOperator)

   - Stream reduce(int initialvalue,BinaryOperator,BinaryOperator)

 

 

public class Main {

              public static void main(String...args) {

                  List<String> l=new ArrayList<>();

                  l.add("Ram");

                  l.add("Sam");

                  l.add("Raj");

                  l.add("Tam");

                  l.add("Tim");

                  l.add("Jim");

                  l.add("Ram");

                  l.add("Ham");

                  System.out.println(l.size());  //8

                 

                  Stream<String> st=l.stream();

                  Stream<String> st1=st.distinct();

                  long val=st1.count();

                  System.out.println(val); //7

                 

                  long val1=l.stream().distinct().count();

                  System.out.println(val1); //7

                 

                  boolean b1=l.stream().distinct().anyMatch((e)->e.startsWith("R"));

                  System.out.println(b1); //true

                  boolean b2=l.stream().distinct().allMatch((e)->e.startsWith("R"));

                  System.out.println(b2); //false

                  boolean b3=l.stream().distinct().noneMatch((e)->e.startsWith("Z"));

                  System.out.println(b3); //true

                 

                  List<Student> l1=new ArrayList<>();

                  l1.add(new Student(23,"PK"));

                  l1.add(new Student(26,"KK"));

                  l1.add(new Student(22,"MK"));

                  l1.add(new Student(21,"SK"));

                  l1.add(new Student(20,"AK"));

                  l1.add(new Student(33,"TK"));

                  l1.add(new Student(24,"BK"));

                  l1.add(new Student(25,"GK"));

                  l1.add(new Student(27,"DK"));

                 

                  Stream<Student> st2=l1.stream().filter((s1)->s1.getId()>25);

                  st2.forEach(System.out::println);

                 

                  Optional opt=Stream.of(3,5,6).reduce((a,b)->a*b);

                  System.out.println(opt.get()); //90

                 

                  Integer i=Stream.of(3,5,6).reduce(2, (a,b)->a*b);

                  System.out.println(i);  //180

                 

                  Optional<String> opt1=Stream.of("lion","ape","tiger").min((c1,c2)->c1.length()-c2.length());

                  System.out.println(opt1.get()); //ape

                 

                  Optional<String> opt2=Stream.of("lion","ape","tiger").max((c1,c2)->c1.length()-c2.length());

                  System.out.println(opt2.get()); //tiger

                 

    }

}

 

map(Function) - intermediate - used to data transformation

              - take one Function functional interface as an argument and return a stream consisting of results generated by applying passed function to each element

 

flatMap(Function) - intermediate - used to data transformation + flattening

              - take one Function functional interface as an argument and return a new stream and that stream is copied to another stream which will return the value

 

 

collect(Collector) - terminal - used to collect the data in List or Set or Map

 

Collectors.toList()

Collectors.toSet()

Collectors.toMap(Function f1,Function f2)

Collectors.joining()

Collectors.counting()

Collectors.toCollection(Supplier) - other than List,Set or Map, if we want to collect in different datatype

Collectors.partitioningBy() - used to split the list based on true or false condition

     - partitioningBy(Predicate)

     - partitioningBy(Predicate, Collector)

Collectors.groupingBy() - used to group the elts based on some condition

     - groupingBy(Function)

     - groupingBy(Function, Collector)

     - groupingBy(Function,Comparator,Collector)

 

 

 

class Customer {

    private int id;

    private String name;

    private String email;

    private List<String> phoneNumbers;

              public Customer(int id, String name, String email, List<String> phoneNumbers) {

                             super();

                             this.id = id;

                             this.name = name;

                             this.email = email;

                             this.phoneNumbers = phoneNumbers;

              }

              public int getId() {

                             return id;

              }

              public void setId(int id) {

                             this.id = id;

              }

              public String getName() {

                             return name;

              }

              public void setName(String name) {

                             this.name = name;

              }

              public String getEmail() {

                             return email;

              }

              public void setEmail(String email) {

                             this.email = email;

              }

              public List<String> getPhoneNumbers() {

                             return phoneNumbers;

              }

              public void setPhoneNumbers(List<String> phoneNumbers) {

                             this.phoneNumbers = phoneNumbers;

              }

   

    

}

 

public class MapVsFlatMap {

     public static List<Customer> getAll() {

        return Stream.of(

                new Customer(101, "john", john@gmail.com, Arrays.asList("397937955", "21654725")),

                new Customer(102, "smith", smith@gmail.com, Arrays.asList("89563865", "2487238947")),

                new Customer(103, "peter", peter@gmail.com, Arrays.asList("38946328654", "3286487236")),

                new Customer(104, "kely", kely@gmail.com, Arrays.asList("389246829364", "948609467"))

        ).collect(Collectors.toList());

    }

    public static void main(String[] args) {

 

      List<Customer> customers = getAll();

 

        //List<Customer>  convert List<String> -> Data Transformation

        //mapping : customer -> customer.getEmail()

        //customer -> customer.getEmail()  one to one mapping, since one customer have one email

        List<String> emails = customers.stream()

                .map(customer -> customer.getEmail())

                .collect(Collectors.toList());

        System.out.println(emails);

 

//customer -> customer.getPhoneNumbers()  ->> one to many mapping

        //customer -> customer.getPhoneNumbers()  ->> one to many mapping

        List<List<String>> phoneNumbers = customers.

                stream().map(customer -> customer.getPhoneNumbers())

                .collect(Collectors.toList());

        System.out.println(phoneNumbers); //creates stream of phone numbers

 

        //List<Customer>  convert List<String> -> Data Transformation

        //mapping : customer -> phone Numbers

        //customer -> customer.getPhoneNumbers()  ->> one to many mapping, since one customer have many phonenumbers

        List<String> phones = customers.stream()

                .flatMap(customer -> customer.getPhoneNumbers().stream())

                .collect(Collectors.toList());

        System.out.println(phones);  //flattens the phone number and prints

    }

}

 

 

public class Main {

              public static void main(String...args) {

                Integer[] a=new Integer[] {1,2,3,4,5};

                List<Integer> l=Arrays.asList(a);

               

                System.out.println(l); //[1,2,3,4,5]

               

                //From JDK10

                //List<Integer> l1=List.of(1,2,3,4,5);

               

                List<Integer> l1=l.stream().map((e)->e*3).collect(Collectors.toList());

                l1.forEach(System.out::println);

                

                List<Integer> l2=l.stream().flatMap((e)->Stream.of(e*2)).collect(Collectors.toList());

                l2.forEach(System.out::println);

               

                String str=Stream.of("one","two","three").collect(Collectors.joining("-"));

                System.out.println(str); //one-two-three

               

                long c=Stream.of("one","two","three").collect(Collectors.counting());

                System.out.println(c); //3

               

                List<String> l3=Stream.of("lions","tigers","bears","toads","toads")

                      .filter((s)->s.startsWith("t"))

                      .collect(Collectors.toList());

                System.out.println(l3);  //[tigers, toads, toads]

               

                List<String> l4=Stream.of("lions","tigers","bears","toads","toads")

                                     .filter((s)->s.startsWith("t")).distinct()

                                     .collect(Collectors.toList());

                               System.out.println(l4);  //[tigers, toads]

                              

                               Set<String> l5=Stream.of("lions","tigers","bears","toads","toads")

                                                   .filter((s)->s.startsWith("t"))

                                                   .collect(Collectors.toSet());

                                             System.out.println(l5);  //[toads, tigers]

                                            

                                             Set<String> l6=Stream.of("lions","tigers","bears","toads","toads","tadpoles")

                                                                  .filter((s)->s.startsWith("t"))

                                                                  .collect(Collectors.toSet());

                                                            System.out.println(l6); //[toads, tadpoles, tigers]

                                                           

                                                            TreeSet<String> l7=Stream.of("lions","tigers","bears","toads","toads","tadpoles")

                                                                                .filter((s)->s.startsWith("t"))

                                                                                .collect(Collectors.toCollection(TreeSet::new));

                                                                          System.out.println(l7); //[tadpoles, tigers, toads]

               

                             Map<String,Integer> m1=Stream.of("lions","tigers","bears","toads")

                                   .collect(Collectors.toMap((k1)->k1, (v1)->v1.length()));

                             System.out.println(m1); //{toads=5, lions=5, bears=5, tigers=6}

                            

                             Map<Boolean,List<String>> m2=Stream.of("lions","tigers","bears","toads","toads","tadpoles")

                             .collect(Collectors.partitioningBy((s1)->s1.length()<=5));

                             System.out.println(m2);//{false=[tigers, tadpoles], true=[lions, bears, toads, toads]}

                            

                             Map<Boolean,Set<String>> m3=Stream.of("lions","tigers","bears","toads","toads","tadpoles")

                                                          .collect(Collectors.partitioningBy((s2)->s2.length()<=5, Collectors.toSet()));

                                                         System.out.println(m3);//{false=[tadpoles, tigers], true=[toads, lions, bears]}

                                                         

                             Map<Integer,List<String>> m4=Stream.of("lions","tigers","bears","toads","ape","lions")

                                   .collect(Collectors.groupingBy((e)->e.length()));

                             System.out.println(m4); //{3=[ape], 5=[lions, bears, toads, lions], 6=[tigers]}

                            

                             Map<Integer,Set<String>> m5=Stream.of("lions","tigers","bears","toads","ape","lions")

                                                 .collect(Collectors.groupingBy((e)->e.length(),Collectors.toSet()));

                                           System.out.println(m5); //{3=[ape], 5=[toads, lions, bears], 6=[tigers]}

}

}




Handson

 

1. Given a list of integers, find the sum of the squares of all even numbers.

2. Given a list of strings (names), concatenate all names that start with the letter 'A' in uppercase and return the concatenated string.

3. Given a list of strings, find the longest word. If multiple words are of the same length, return the first one.

4. Given a list of strings, count how many times each word appears in the list.

5. Given a list of integers, calculate the average of only the positive numbers.

6. Given a list of integers, find the distinct even numbers.

7. Given a list of integers, find the first odd number greater than 5.

8. Given a list of integers, check if all numbers are positive.

9. Given a list of integers, calculate the sum of squares of even numbers.

10. Write a Stream operation to find the longest string from a list of strings.

No comments:

Post a Comment