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
Related
This question already has answers here:
Zip two lists into an immutable multimap in Java 8 with Guava?
(3 answers)
Closed 2 years ago.
I have two streams
Stream<Key> keys;
Stream<Value> values;
I want combine them into a single Map
Map<Key, Value> result = someMagicMethod(keys, values);
Is there any elegant way to do that?
I know there is a method called Stream.concat, but it's not for this case.
Guava Streams.zip for streams without random access
If Guava is available at runtime, then the following can help:
List<String> keys = Arrays.asList("One", "Two");
List<Integer> values = Arrays.asList(1, 2);
Map<String, Integer> zipped = Streams.zip(keys.stream(), values.stream(), SimpleEntry::new)
.collect(Collectors.toMap(Collectors.toMap(Entry::getKey, Entry::getValue)));
System.out.println(zipped);
You can first collect both streams to a List.
List<Key> keyList = keys.collect(Collectors.toList());
List<Value> valueList = values.collect(Collectors.toList());
Map<Key, Value> map = IntStream.range(0, keyList.size())
.boxed().collect(Collectors.toMap(keyList::get, valueList::get));
System.out.println(map);
This question already has answers here:
Every combination of 2 strings in List Java 8 [duplicate]
(1 answer)
Should I use Java 8 Streams Api to combine two Collections?
(2 answers)
Closed 2 years ago.
I have two Lists:
List<Object1> listOne = provider.getObjects().stream().collect(Collectors.toList());
List<Object2> listTwo = provider2.getObjects().stream().collect(Collectors.toList());
Now I want create List containg all possible Object1-Object2 combinations: List<ObjectCombinations> result;
class ObjectCombinations {
Object1 object1;
Object2 object2;
public ObjectCombinations(Object1 object1, Object2 object2) {
this.object1 = object1;
this.object2 = object2;
}
}
How is that possible with java 8 streams?
You can use flatMap to get all the combinations:
List<ObjectCombinations> result =
listOne.stream()
.flatMap(o1 -> listTwo.stream()
.map(o2 -> new ObjectCombinations(o1,o2)))
.collect(Collectors.toList());
First you create a Stream<Object1>, then you use flatMap to combine each element of that stream with all the elements of listTwo, and create the ObjectCombinations instances, which you collect to a List.
You can use flatMap where you can stream over 2nd list and create ObjectCombinations and flatten the list.
List<ObjectCombinations> res =
listOne.stream()
.flatMap(a -> listTwo.stream().map(b -> new ObjectCombinations(a,b)))
.collect(Collectors.toList());
This question already has answers here:
Group a list of objects by an attribute
(13 answers)
Closed 2 years ago.
I have a List<Emp> where Emp is name, id, address.
value saved is like
("Name1, 11, Delhi"),
("Name1, 12, Chennai"),
("Name2, 13, Delhi"),
("Name3, 14, Delhi"),
("Name4, 15, Delhi")
I am trying to create a Map with Key as Name and value as list of Emp which has those name.
This is what I tried, and it's working fine, but I am looking for a better way.
Map<String, List<Emp>> nameMap = new HashMap<>();
empList.forEach(
empDto -> {
List<EmpDto> empDtoName = new ArrayList<>();
String name = empDto.getName();
if (nameMap .containsKey(name))
{
empDtoName = nameMap.get(name);
}
empDtoName.add(userRoleDto);
userRoleMap.put(usrNwId, empDtoName);
}
);
Use a Stream and collect its elements with a groupingBy collector:
Map<String, List<Emp>> nameMap =
empList.stream()
.collect(Collectors.groupingBy(Emp::getName));
This question already has answers here:
How can I initialize an ArrayList with all zeroes in Java?
(5 answers)
Closed 4 years ago.
I want to transform a list of String to a map, where the key of map is a simple increment.
For example:
List<String> result = new ArrayList<String>();
result.add("hello");
result.add("Java");
Pretend result:
Map<Integer, String> mapOfList;
map(1, "Hello");
map(2, "Java");
Try:
AtomicInteger atomic=new AtomicInteger(0);
mapOfList=result.stream().collect(atomic.incrementAndGet(), s -> s);
You need to iterate. Here's one-line using an int stream:
IntStream.range(0, fillMyList.size()).forEach(i -> fillMyList.set(i, ""));
This question already has answers here:
Convert List of List into list in java
(5 answers)
Closed 5 years ago.
I have a multimap Map<T,List<L>> map and I need a list with all the values of the values from the map, namely List<L>. With map.values() I get a List<List<L>>, but thats not what I want.
Does someone know a clean solution without looping?
If you are using Java 8, you could collect all L values from all List<L>s in a single List<L> by Stream#flatMap:
final List<L> list = map
// get a Collection<List<L>>
.values()
// make a stream from the collection
.stream()
// turn each List<L> into a Stream<L> and merge these streams
.flatMap(List::stream)
// accumulate the result into a List
.collect(Collectors.toList());
Otherwise, a for-each approach with Collection#addAll can be applied:
final List<L> list = new ArrayList<>();
for (final List<L> values : map.values()) {
list.addAll(values);
}