Java 8 : findAny and findFirst Operations

In the below code example, we would see the usage of the 2 operations provided in Java 8 namely findAny and findFirst

import java.util.*;
import java.util.stream.*;

public class Java8GroupByExample {
    public static void main(String args[]) {
      
     List<Integer> numList = Java8GroupByExample.getNumbersList();
     Integer first = numList.stream().findFirst().get();
     Integer any = numList.stream().findAny().get();
     
     System.out.println(first);
     System.out.println(any);
      
    }
    
    private static List<Integer> getNumbersList(){
        
        List<Integer> list = new ArrayList<Integer>();
        list.add(5);
        list.add(12);
        list.add(9);
        list.add(15);
        list.add(25);
        list.add(4);
        
        return list;
    }
    
}

Java 8 : count, max and min operations

Here in this code example we will go through the max, min and count operations which we can use as part of new functionality introduced by Java 8.

count() – Returns the count of elements in the stream.

max() – This method returns the max element of a stream. It returns an Optional. We should do a get() call on that to get the actual object.

min() – This method returns the max element of a stream. It returns an Optional. We should do a get() call on that to get the actual object.

import java.util.*;
import java.util.stream.*;

class Student {

    private String name;
    private int round;
    private int points;
    
    public Student(String name, int round, int points) {
        super();
        this.name = name;
        this.round = round;
        this.points = points;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getRound() {
        return round;
    }
    public void setRound(int round) {
        this.round = round;
    }
    public int getPoints() {
        return points;
    }
    public void setPoints(int points) {
        this.points = points;
    }
}

public class Java8GroupByExample {
    public static void main(String args[]) {
      
     List<Integer> numList = Java8GroupByExample.getNumbersList();
     Long count = numList.stream().count();
     System.out.println("The count is "+count);
     
     Integer max = numList.stream().max(Comparator.comparing(Integer::valueOf)).get();
     System.out.println("The max is "+max);
     
     Integer min = numList.stream().min(Comparator.comparing(Integer::valueOf)).get();
     System.out.println("The min is "+min);
     
     List<Student> studList = Java8GroupByExample.createStudList();
     
     Comparator<Student> comparator = Comparator.comparing(Student::getPoints);
     Student minStud = studList.stream().min(comparator).get();
     System.out.println("The student with min points is "+minStud.getName());
     
     Student maxStud = studList.stream().max(comparator).get();
     System.out.println("The student with max points is "+maxStud.getName());
      
    }
    
    private static List<Integer> getNumbersList(){
        
        List<Integer> list = new ArrayList<Integer>();
        list.add(5);
        list.add(12);
        list.add(9);
        list.add(15);
        list.add(25);
        list.add(4);
        
        return list;
    }
    
    public static List<Student> createStudList()
    {
        List<Student> studList=new ArrayList<Student>();
    
        Student s1=new Student("Nathan",1,500); 
        Student s2=new Student("Chris",1,1000);  
        Student s3=new Student("David",1,100);
        Student s4=new Student("James",1,300);
        Student s5=new Student("Mike",1,3000);
    
        studList.add(s1);
        studList.add(s2);
        studList.add(s3);
        studList.add(s4);
        studList.add(s5);
    
        return studList;
    }
    
}

Java 8 : Group by Operation With Example

Let’s look into the group by operation provided by Java 8 for grouping elements together. It is similar to the one provided by SQL.

import java.util.*;
import java.util.stream.*;
import java.util.function.Function;

public class MyClass {
    public static void main(String args[]) {
      List<String> items = Arrays.asList("apple","guava","banana","apple","guava","orange","banana","apple");
      Map<String,Long> result = items.stream().collect(Collectors.groupingBy(Function.identity(),Collectors.counting()));
      
      System.out.println("The count of all fruits are as follows : "+result);
      
    }
}

So if you see above, the fruits were grouped by their respective counts.

Let’s group by using Objects.

Here we are grouping by the student name to find his total points scored in all the rounds.

import java.util.*;
import java.util.stream.*;

class Student {

    private String name;
    private int round;
    private int points;
    
    public Student(String name, int round, int points) {
        super();
        this.name = name;
        this.round = round;
        this.points = points;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getRound() {
        return round;
    }
    public void setRound(int round) {
        this.round = round;
    }
    public int getPoints() {
        return points;
    }
    public void setPoints(int points) {
        this.points = points;
    }
}

public class Java8GroupByExample {
    public static void main(String args[]) {
      
      List<Student> studList = Java8GroupByExample.createStudList();
      
      Map<String,Integer> studPoints = 
      studList.stream().collect(Collectors.groupingBy(Student::getName,Collectors.summingInt(Student::getPoints)));
      System.out.println("Grouped by student total points : "+studPoints);
      
    }
    
    public static List<Student> createStudList()
    {
        List<Student> studList=new ArrayList<Student>();
    
        Student s1=new Student("Nathan",1,500);    
        Student s2=new Student("Nathan",2,1200);
        Student s3=new Student("Nathan",3,1500);
        Student s4=new Student("Chris",1,1000);
        Student s5=new Student("Chris",2,2000);
        Student s6=new Student("Chris",3,200);    
        Student s7=new Student("David",1,100);
        Student s8=new Student("David",2,1000);
        Student s9=new Student("David",3,500);
        Student s10=new Student("James",1,300);
        Student s11=new Student("James",2,2600);
        Student s12=new Student("Mike",1,3000);
    
        studList.add(s1);
        studList.add(s2);
        studList.add(s3);
        studList.add(s4);
        studList.add(s5);
        studList.add(s6);
        studList.add(s7);
        studList.add(s8);
        studList.add(s9);
        studList.add(s10);
        studList.add(s11);
        studList.add(s12);
    
        return studList;
    }
    
}

Java 8 : allMatch, anyMatch and noneMatch

allMatch, anyMatch and noneMatch methods introduced in Java 8 can be used with Lambda Expressions to find if any word or letter exists in a list of strings or not.

Kindly check the below code to see the behavior of the 3 methods.

import java.util.*;
import java.util.stream.*;

public class Java8MatchExample {
    public static void main(String args[]) {

      List<String> namesList = Java8MatchExample.getNamesList();
      boolean respMatch = namesList.stream().allMatch(n->n.contains("z"));
      
      if(respMatch==true){
          System.out.println("All words contain z");
      }
      else{
          System.out.println("Not all words contain z");
      }
      
      boolean respAnyMatch = namesList.stream().anyMatch(n->n.contains("z"));
      
      if(respAnyMatch==true){
          System.out.println("Atleast one word contains z");
      }
      else{
          System.out.println("None of the words contain z");
      }
      
      boolean respNoneMatch = namesList.stream().noneMatch(n->n.contains("y"));
      
      if(respNoneMatch==true){
          System.out.println("None of the words contains y");
      }
      else{
          System.out.println("One or more words contain y");
      }
      
    }
    
    private static List<String> getNamesList(){
        
        List<String> list = new ArrayList<String>();
        list.add("nathan");
        list.add("chris");
        list.add("david");
        list.add("james");
        list.add("mike");
        list.add("zack");
        
        return list;
    }
    
}

Java 8 : Distinct Operation

In the below example, you will see how to use the distinct operation on a list of elements to fetch the list of all distinct elements.

If the elements is a Custom User Class, then we would need to override the equals and hashCode method as there would be a need to correctly check for equality of 2 objects.

Kindly find the below code.

import java.util.*;
import java.util.stream.*;

class Student {

    private String name;
    private int empId;
    
    public Student(String name, int empId) {
        super();
        this.name = name;
        this.empId = empId;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getId() {
        return empId;
    }
    public void setId(int empId) {
        this.empId = empId;
    }
    
    @Override
    public boolean equals(Object o)
    {
        if(this == o)
                return true;
              
            if(o == null || o.getClass()!= this.getClass())
                return false;
                
            Student st = (Student) o;     
                
            return (st.getName().equals(this.getName()) && st.getId() == this.getId());
    }
    
    @Override  
    public int hashCode()
    {
          return 1;
    }
    
}

public class Java8DistinctExample {
    public static void main(String args[]) {

      List<Integer> numList = Java8DistinctExample.getNumList();
      List<Integer> distinctList = numList.stream().distinct().collect(Collectors.toList());
      
      System.out.println("Distinct elements : "+distinctList);
      
      List<Student> studList = Java8DistinctExample.createStudList();
      List<Student> distinctStudList = studList.stream().distinct().collect(Collectors.toList());
      
      System.out.println("Distinct student objects : "+distinctStudList);
      
    }
    
    private static List<Integer> getNumList(){
        
        List<Integer> list = new ArrayList<Integer>();
        list.add(10);
        list.add(10);
        list.add(102);
        list.add(109);
        list.add(122);
        list.add(134);
        list.add(134);
        list.add(148);
        
        return list;
    }
    
    public static List<Student> createStudList()
    {
        List<Student> studList=new ArrayList<Student>();
    
        Student s1=new Student("Aalo",215013);
        Student s2=new Student("Aalo",215013);
        Student s3=new Student("Sumo",215012);
        Student s4=new Student("Shiji",222432);
        Student s5=new Student("Lufo",310131);
        Student s6=new Student("Lufo",310131);
        Student s7=new Student("Zishi",310135);
    
        studList.add(s1);
        studList.add(s2);
        studList.add(s3);
        studList.add(s4);
        studList.add(s5);
        studList.add(s6);
        studList.add(s7);
    
        return studList;
    }
    
}

Java 8 : Filter, reduce and limit operations

Kindly find the below code in which we use the filter, reduce and limit operations using Java 8 Lambda Expressions.

import java.util.*;
import java.util.stream.*;


public class Java8OpsExample {
    public static void main(String args[]) {

      List<String> elemList = Java8OpsExample.getNamesList();
      
      List<String> filteredList = elemList.stream().filter(e -> e.substring(0,1).equals("C")).collect(Collectors.toList());
      System.out.println("The filtered list is : "+filteredList); 
      
      List<String> limitList = elemList.stream().limit(3).collect(Collectors.toList());
      System.out.println("The limited list is : "+limitList);
      
      String reduce = elemList.stream().reduce(" ",(acc,el) -> acc + "|" + el);
      System.out.println("The reduced value is : "+reduce);
      
    }
    
    private static List<String> getNamesList(){
        
        List<String> list = new ArrayList<String>();
        list.add("Nathan");
        list.add("Chris");
        list.add("David");
        list.add("James");
        list.add("Mike");
        
        return list;
    }
    
}

Java 8 : Merge HashMaps Using Lambda Expressions

Below is the source code for merging 2 HashMaps. Keys would be same in both maps. Values may or may not be same. If values are same for a particular key, distinct value would be shown in the final merged map. If different, it would be concatenated comma separated.

import java.util.*;
import java.util.stream.*;


public class Java8MapMerge {
    public static void main(String args[]) {

      HashMap<Integer,String> map1 = new HashMap<>();
      map1.put(1,"A");
      map1.put(2,"B");
      map1.put(3,"C");
      map1.put(5,"E");
      
      HashMap<Integer,String> map2 = new HashMap<>();
      
      map2.put(1,"G");
      map2.put(2,"B");
      map2.put(3,"C");
      map2.put(4,"D");
      
      map2.forEach((key,value) -> map1.merge(key,value,(v1,v2)->v1.equalsIgnoreCase(v2)?v1:v1+","+v2));
      
      System.out.println(map1);
      
    }
    
}

Java 8 : Sorting of elements

Below is the source code for sorting elements using Java 8 Lambda Expressions.

import java.util.*;
import java.util.stream.*;

class Student {

    private String name;
    private int empId;
    
    public Student(String name, int empId) {
        super();
        this.name = name;
        this.empId = empId;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getId() {
        return empId;
    }
    public void setId(int empId) {
        this.empId = empId;
    }
}

public class Java8SortingExample {
    public static void main(String args[]) {

      List<String> namesList = Java8SortingExample.getNamesList();
      namesList.sort((a,b) -> a.length()-b.length());
      System.out.println("Sorting elements by length : "+namesList);
      
      namesList.sort(Comparator.comparing(String::length));
      System.out.println("Sorting elements by length Using Comparator: "+namesList);
      
      List<String> sortedNamesList = namesList.stream().sorted((i1,i2) -> i1.compareTo(i2)).collect(Collectors.toList());
      System.out.println("Sorting elements by name : "+sortedNamesList);
      
      List<Student> studList = Java8SortingExample.createStudList();
      
      studList.sort(Comparator.comparing(s ->s.getName()));
      List<String> sortedStudList = studList.stream().map(Student::getName).collect(Collectors.toList());
      System.out.println("Sorting student objects by name : "+sortedStudList);
      
    }
    
    private static List<String> getNamesList(){
        
        List<String> list = new ArrayList<String>();
        list.add("Nathan");
        list.add("Chris");
        list.add("David");
        list.add("James");
        list.add("Mike");
        
        return list;
    }
    
    public static List<Student> createStudList()
    {
        List<Student> studList=new ArrayList<Student>();
    
        Student s1=new Student("Aalo",215013);    
        Student s2=new Student("Sumo",215012);
        Student s3=new Student("Shiji",222432);
        Student s4=new Student("Lufo",310131);
        Student s5=new Student("Zishi",310135);
    
        studList.add(s1);
        studList.add(s2);
        studList.add(s3);
        studList.add(s4);
        studList.add(s5);
    
        return studList;
    }
    
}

Java 8 : Date API

Compared to the java.util.date API, the new date API’s are immutable and thread safe. Alos it has a lot of new features and methods compared to it’s previous counterpart.

API’s introduced in Java 8 are:

  1. LocalDate
  2. LocalTime
  3. LocalDateTime
import java.time.*;

public class MyClass {  
public static void main(String[] args) {  
    //current date
    LocalDate date = LocalDate.now();
    System.out.println("Current date is "+
                        date);
  
  
    // current time
    LocalTime time = LocalTime.now();
    System.out.println("Current time is "+
                        time);
      
  
    // current time and date
    LocalDateTime current = LocalDateTime.now();
    System.out.println("Current date and time : "+
                        current);

// To format a date into a particular type
    DateTimeFormatter format =
      DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss"); 
   
    String formattedDate = current.format(format); 
    
    System.out.println("Formatted date is "+
                        formattedDate);
  
  
    //Get month,day from current date time
    Month month = current.getMonth();
    int day = current.getDayOfMonth();
    System.out.println("Month : "+month+" day : "+
                        day);                      
}  
}  

Java 8 : Method References

Method references are some special type of Lambda Expressions which only execute one method.

Syntax for MR is as below:

object::methodName

Let us look into some examples. Things would clear.

public static void main(String[] args)
    {
        List<String> studList=Arrays.asList(new String[] {"John", "David","Lionel","Cristiano"});
        
        System.out.println("Without Method Reference");
        studList.stream().forEach(
                stud -> System.out.println(stud)
                );
 
        System.out.println("\n");
        System.out.println("With Method Reference");
        studList.stream().forEach(
                System.out::println
            );
 
    }

As seen above, you can see the usage of a method reference. The println method of System.out object is applied to each element of the List. You can see the List printed above.

Let’s take an example involving a Custom Class and using method reference with it.


import java.util.*;
import java.util.stream.*;

class Student {

    private String name;
    private int empId;
    
    public Student(String name, int empId) {
        super();
        this.name = name;
        this.empId = empId;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getId() {
        return empId;
    }
    public void setId(int empId) {
        this.empId = empId;
    }
}
 
 
public class MyClass {
    
    public static void main(String[] args)
    {
        List<Student> studList = createStudList();
        
        List l = studList.stream().map(Student::getName).collect(Collectors.toList());
        System.out.println(l);
 
    }
 
    public static List<Student> createStudList()
    {
        List<Student> studList=new ArrayList<Student>();
 
        Student s1=new Student("Sumo",21);
        Student s2=new Student("Shiji",22);
        Student s3=new Student("Lufo",31);
 
        studList.add(s1);
        studList.add(s2);
        studList.add(s3);
 
        return studList;
    }
 
}

Here we iterated over the list containing student objects and calling the getName method by method reference for each element, we mapped it to name and collected it into a list.

Let’s take another example.

import java.util.function.*;

class Addition{
public static int add(int a, int b){
return a+b;
}
}
public class MyClass {
public static void main(String[] args) {
BiFunction addFunction = Addition::add;
int output = addFunction.apply(100, 200);
System.out.println(output);
}
}

We used a Java 8 Function Interface here to add 2 numbers.

Hope the examples were clear. Thanks for reading.