Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAVA-8 streams collect advanced usage

package streams;

import java.util.Arrays;
import java.util.List;

class Student{
    String name;
    int age;
    String type;

    public Student(){}

    public Student(String name, int age, String type) {
        this.name = name;
        this.age = age;
        this.type = type;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", type='" + type + '\'' +
                '}';
    }

    public static List<Student> generateData() {

        List<Student> st = Arrays.asList(new Student("Ashish", 27, "College"),
                new Student("Aman", 24, "School"),
                new Student("Rahul", 18, "School"),
                new Student("Ajay", 29, "College"),
                new Student("Mathur", 25, "College"),
                new Student("Modi", 28, "College"),
                new Student("Prem", 15, "School"),
                new Student("Akash", 17, "School"));
        return st;
    }
}

//AdvancedStreamingP2 class uses the Student class

package streams;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.*;

public class AdvancedStreamingP2 {

    public static void main(String[] args) {

        List<Student> studentList = Student.generateData();
        System.out.println("\n---------- Extracting Student Name with Max Age by Type -----------");
        Map<String, Optional<Student>> stuMax = studentList.stream().collect(groupingBy(Student::getType, maxBy(comparing(Student::getAge))));
        stuMax.forEach((k, v) -> System.out.println("Key : " + k + ", Value :" + v.get()));
    }
}

I want to extract the student name, with the max age, grouping student by Type. Is it possible by using any combination in "collect" itself?

I want the output like :

---------- Extracting Student Name with Max Age by Type -----------

Key : School, Value : Aman
Key : College, Value : Ajay
like image 523
Ashu Avatar asked Nov 26 '15 09:11

Ashu


People also ask

What is the use of collect in Java 8?

collect() is one of the Java 8's Stream API's terminal methods. It allows us to perform mutable fold operations (repackaging elements to some data structures and applying some additional logic, concatenating them, etc.) on data elements held in a Stream instance.

How do you collect data from a stream?

Gather all the stream's items in the collection created by the provided supplier. Count the number of items in the stream. Sum the values of an Integer property of the items in the stream. Calculate the average value of an Integer property of the items in the stream.

Does Java 8 stream improve performance?

In Java8 Streams, performance is achieved by parallelism, laziness, and using short-circuit operations, but there is a downside as well, and we need to be very cautious while choosing Streams, as it may degrade the performance of your application.


1 Answers

Yes, you can use Collectors.collectingAndThen. This collector adapts an existing collector to perform an additional finisher operation. In this case, the finisher operation simply returns the name of the Student.

Map<String, String> stuMax = 
    studentList.stream()
               .collect(groupingBy(
                    Student::getType, 
                    collectingAndThen(maxBy(comparing(Student::getAge)), v -> v.get().getName()) 
               ));

Output:

---------- Extracting Student Name with Max Age by Type -----------
Key : School, Value :Aman
Key : College, Value :Ajay

Side-note: instead of using comparing, you can use comparingInt since Person.getAge() returns an int: this avoids unnecessary boxing.

like image 65
Tunaki Avatar answered Oct 25 '22 12:10

Tunaki