Home > Blockchain >  How to get unique values from list of list and store in set by using streams
How to get unique values from list of list and store in set by using streams

Time:11-18

I have classes Employee and Address as follows:

public static class Employee {
    private List<Address> address;
    
    // getters, etc.
}

public static class Address {
    private String city;
    
    // getters, etc.
}

I am learning streams, I am trying to iterate over the objects from list of list and create a set of unique values. I was able to get it working by using nested for loop. How can I convert below code to streams?

public static Set<String> getCityUniquName(List<Employee> emp){

    Set<String> cityUniquName = new HashSet<>();
    for(Employee e: emp){
        List<Address> addList = e.getAddress();
        for(Address add: addList){
            cityUniquName.add(add.getCity());
        }
    }
   return cityUniquName;
}

CodePudding user response:

Use flatMap to flatten the Address list and then use map to get the city from each Address object and then collect into Set

Set<String> cityUniquName = emp.stream()
                .flatMap(Employee::getAddress)
                .map(Address::getCity)
                .collect(Collectors.toSet());

CodePudding user response:

Since each Employee is associated with a collection of Address instances, you need to apply of the stream operations that allow to flatten the data, namely either flatMap(), or mapMulty().

Note that flatMap() expects a function producing a Stream,not a Collection like shown in another answer.

Stream.flatMap

To turn a Stream of Employee into a Stream of Address in the mapper function of flatMap() we need to extract the collection of addresses and create a stream over it.

The only thing left is to get the city name and collect the result into a set.

public static Set<String> getCityUniqueName(List<Employee> emp) {
    
    return emp.stream()
        .flatMap(e -> e.getAddress().stream())
        .map(Address::getCity)
        .collect(Collectors.toSet());
}

Stream.mapMulti

mapMulti() expects a BiConsumer, which in turn takes two arguments: stream element (having an initial type) and a Consumer of the resulting type. Every object offered to the consumer would appear in the resulting stream.

public static Set<String> getCityUniqueName1(List<Employee> emp) {
    
    return emp.stream()
        .<Address>mapMulti((e, c) -> e.getAddress().forEach(c))
        .map(Address::getCity)
        .collect(Collectors.toSet());
}
  • Related