Java 8 stream: list to flat map grouped by [duplicate] - java

This question already has answers here:
Java 8 List<V> into Map<K, V>
(23 answers)
Closed 5 years ago.
I have following situation. (pseudocode)
class A {
id;
List<B> bs;
}
class B {}
I wonder how to convert List os As -> Map of Bs
List<A> as;
// the Map key is A.id (Map<A.id, List<B>>)
Map<Integer, List<B>> bs = as.stream()
.map(a ->a.getBs())
.collect(// I dont know what to add here ???);

Seems like you want sometime like this:
Map<Integer, List<B>> bs = as.stream()
.collect(Collectors.toMap(A::getId, A::getBs));

Related

Converting String Collection to a Map with input as the key mapper [duplicate]

This question already has answers here:
Aggregate List<String> into HashMap<String, T> using Stream API
(1 answer)
Collectors.toMap() keyMapper -- more succinct expression?
(3 answers)
Closed 2 years ago.
Here's an example:
Map<String, Student> getStudentsById(Collection<String> ids) {
return ids.stream()
.collect(Collectors.toMap(<id-here>, id -> new Student(id))
}
I'm not sure how to use Collectors.toMap, so that key is the stream element (here in case the ID), and value is some object constructed from the key.
You are passing a String and a Student to Collectors.toMap(), when you should be passing a Function<? super String,? extends String> and a Function<? super String,? extends Student>.
It should be:
Map<String, Student> idToStudent = ids.stream()
.collect(Collectors.toMap(Function.identity(), id -> new Student(id)));

Java Group objects by values in object's list [duplicate]

This question already has answers here:
How to convert List<V> into Map<K, List<V>>, with Java 8 streams and custom List and Map suppliers?
(3 answers)
Converting List<MyObject> to Map<String, List<String>> in Java 8 when we have duplicate elements and custom filter criteria
(4 answers)
How to convert List<String> to Map<String,List<String>> based on a delimeter
(5 answers)
Closed 2 years ago.
Problem
I have a list of objects like:
Class MyObj {
private List<Integer> categories;
private String name;
}
I want to map the list of objects to a Map<Integer, List<MyObj>> using a single stream chain.
Example
MyObj obj1 = new MyObj("name1", Arrays.asList(1, 2, 3));
MyObj obj2 = new MyObj("name2", Arrays.asList(1, 4, 3));
MyObj obj3 = new MyObj("name3", Arrays.asList(4));
List<MyObj> objsList = Arrays.asList(obj1, obj2, obj3);
// Here is what Im trying to accomplish:
// a map like -> **{1: [obj1, obj2], 2: [obj1], 3: [obj1, obj2], 4: [obj2, obj3]}**
Map<Integer, List<MyObj>> = objsList.stream
...help
Looking for a map -> {1: [obj1, obj2], 2: [obj1], 3: [obj1, obj2], 4: [obj2, obj3]}
I think the answer is obvious, but I cant seem to get it to work and having a hard time searching. Thank you in advance
You can stream the List from every MyObj and collect Integer and MyObj as pair and then use Collectors.groupingBy
Map<Integer,List<MyObj>> result = objsList.stream()
.flatMap(obj->obj.getCategories().stream().map(i-> Map.entry(i,obj)))
.collect(Collectors.groupingBy(Map.Entry::getKey,Collectors.mapping(Map.Entry::getValue,Collectors.toList())));
Note : Map.entry is from java 9, you can use new AbstractMap.SimpleEntry<Integer, MyObj>(i, obj) for java 8

How to get map from list of object using stream? [duplicate]

This question already has answers here:
Java 8 List<V> into Map<K, V>
(23 answers)
Closed 2 years ago.
I have class country:
class Country {
private String code;
private String name;
}
I need to do from list of Countries to Map with code and name.
I tried to
Map<String, String> countryNames = countries.stream()
.collect(Collectors.groupingBy(Country::getCode, Country::getName));
But it is not right. How to collect correct?
I assume you want code as the key and name as the value. In that case, you need to use Collectors.mapping as the downstream collector to Collectors.groupingBy. Like this:
Map<String, List<String>> countryNames = countries.stream()
.collect(Collectors.groupingBy(Country::getCode,
Collectors.mapping(Country::getName, Collectors.toList())));
Note that this will return the values as a list of strings, as the names are grouped in a list (by Collectors.toList()) if there are multiple countries with the same code.
If you know that each code only appears once in the list, you can use Collectors.toMap instead.
Map<String, String> countryNames = countries.stream()
.collect(Collectors.toMap(Country::getCode, Country::getName));

Java 8 convert Map<Integer, List<String>> to Map<String, List<Integer>> with [duplicate]

This question already has answers here:
How to swap arrayMap values and keys in Java
(4 answers)
Closed 6 years ago.
I have a Map is a map to a list of values but I need to inverse it so that
Map<Integer, List<String>>
becomes
Map<String, List<Integer>>
For example I have
1 -> { A, B, C }
2 -> { B }
3 -> { A, C }
and I want to see
A -> { 1, 3 }
B -> { 1, 2 }
C -> { 1, 3 }
Is there any easier way in Java 8 to do this than having to iterate through the map entries and create a set entry if it does not exist, and add to the list etc? I keep thinking it is really obvious but I cannot work it out.
Thanks in advance
Untested, but you could do something like this:
mapIntToStrings.entrySet().stream()
.flatMap(entryIntToStrings -> entryIntToStrings.getValue().stream()
.map(str -> new AbstractMap.SimpleEntry<>(entryIntToStrings.getKey(), str)))
.collect(groupingBy(Map.Entry::getValue, mapping(Map.Entry::getKey, toList())))

Java8 Lambda: concat list [duplicate]

This question already has answers here:
How can I turn a List of Lists into a List in Java 8?
(12 answers)
Closed 5 years ago.
I am trying to concat list of a stream and process it.
class A {
public List<B> bList;
}
List<A> aList;
aList.stream().map(a -> a.bList)....
Here i get several list of b.
But, I would like to collect all my b in only one list. Any ideas ?
That's what flatMap is for :
List<B> bList = aList.stream()
.flatMap(a -> a.bList.stream())
.collect(Collectors.toList());

Categories