Consider the below WorkExperience
class:
public class WorkExperience {
private int year;
private List<Skills> skill;
public WorkExperience(int year, List<Skills> skill) {
this.year = year;
this.skill = skill;
}
//getter setter
}
public class Skills {
private String skills;
public Skills(String skills) {
this.skills = skills;
}
@Override
public String toString() {
return "Skills [skills=" + skills + "]";
}
}
let's say I want to group by my skills by year, this is how we can do groupBy
by year:
public static void main(String[] args) {
List<Skills> skillSet1 = new ArrayList<>();
skillSet1.add(new Skills("Skill-1"));
skillSet1.add(new Skills("Skill-2"));
skillSet1.add(new Skills("Skill-3"));
List<Skills> skillSet2 = new ArrayList<>();
skillSet2.add(new Skills("Skill-1"));
skillSet2.add(new Skills("Skill-4"));
skillSet2.add(new Skills("Skill-2"));
List<Skills> skillSet3 = new ArrayList<>();
skillSet3.add(new Skills("Skill-1"));
skillSet3.add(new Skills("Skill-9"));
skillSet3.add(new Skills("Skill-2"));
List<WorkExperience> workExperienceList = new ArrayList<>();
workExperienceList.add(new WorkExperience(2017,skillSet1));
workExperienceList.add(new WorkExperience(2017,skillSet2));
workExperienceList.add(new WorkExperience(2018,skillSet3));
Map<Integer, Set<List<Skills>>> collect = workExperienceList.stream().collect(
Collectors.groupingBy(
WorkExperience::getYear,
Collectors.mapping(WorkExperience::getSkill, Collectors.toSet())
)
);
}
groupBy
is returning: Map<Integer, Set<List<Skills>>>
but what I need is: Map<Integer, Set<Skills>>
How to convert List stream into single Container?
The standard solution is to use the Stream. flatMap() method to flatten a List of Lists. The flatMap() method applies the specified mapping function to each element of the stream and flattens it.
The Collector class is used to collect the elements of the Stream into a collection. This class has the toList () method, which converts the Stream to a List. This example is similar to the previous one except that we used the Collector.toList () method instead of the Collectors.toCollection () method.
In such simple usecases, Stream.collect () API is best suited along with Collectors.toList (). Stream<String> tokenStream = Stream.of ("A", "B", "C", "D"); Program output. 2. Collecting Stream into LinkedList The given example is only slightly different from the first example. Here, we are collecting the Stream items into a LinkedList.
Content in Stream (Classic) is divided into five container types: Stream group (Videos in Stream group) (if you didn't migrate from office 365 video, your tenant would not have it) Orphaned container (Videos with no owner) [Not available in Preview] We'll choose the default destination for some types of containers, which admins can override.
A Stream is a collection of objects. A Stream doesn’t store any data, and therefore it is not a data structure. The Stream was added to the Java 8 version, whereas a List is an interface that stores ordered collections. In this tutorial, we will look into converting a Stream to a List.
An alternative to flatMapping
using Java 8 features only would be
Map<Integer, Set<Skills>> map = workExperienceList.stream()
.collect(Collectors.toMap(
WorkExperience::getYear,
we -> new HashSet<>(we.getSkill()),
(s1, s2)-> { s1.addAll(s2); return s1; }));
you may optimize this a bit
Map<Integer, Set<Skills>> map = workExperienceList.stream()
.collect(Collectors.toMap(
WorkExperience::getYear,
we -> new HashSet<>(we.getSkill()),
(s1, s2) -> {
if(s1.size() > s2.size()) { s1.addAll(s2); return s1; }
else { s2.addAll(s1); return s2; }
}));
We can use Collectors.flatMapping
collector added in Java-9. By using flatMapping
, we can flatten the intermediate Lists into a single container. flatMapping
can be used in the cases where elements of the original stream are convertible to a stream.
workExperienceList.stream().collect(Collectors.groupingBy(
WorkExperience::getYear,
Collectors.flatMapping(workexp -> workexp.getSkill().stream(),
Collectors.toSet())));
API Note:
The flatMapping() collectors are most useful when used in a multi-level reduction, such as downstream of a groupingBy or partitioningBy.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With