Reputation: 61
Input: List<Foo> rawdata
Desired Output: Map<Foo, Bar>
Method implementation: Java 8
public Map<Foo, Bar> getMap(List<Foo> rawdata) {
rawData.stream().flatmap(d -> {
val key = method1(d);
val value = method2(d);
})
// Now I want to create a map using the Key/Value
// pair which was obtained from calling method 1 and 2.
}
I did try this:
public Map<Foo, Bar> getMap(List<Foo> rawdata) {
rawData.stream()
.flatmap(
d -> {
val key = method1(d);
val value = method2(d);
return Stream.of(new Object[][]{key, value});
})
.collect(Collectors.toMap(
key -> key[0],
key -> key[1]));
}
However want to see if there is less expensive way of doing this or any better way.
Upvotes: 1
Views: 1087
Reputation:
You can use toMap(keyMapper,valueMapper,mergeFunction)
method with three parameters that allows to merge duplicates into a list, for example:
List<String[]> list = List.of(
new String[]{"Foo1", "Bar1"},
new String[]{"Foo1", "Bar2"},
new String[]{"Foo2", "Baz"});
Map<String, List<String>> map1 = list.stream()
.collect(Collectors.toMap(
e -> e[0],
e -> new ArrayList<>(List.of(e[1])),
(list1, list2) -> {
list1.addAll(list2);
return list1;
}));
System.out.println(map1);
// {Foo1=[Bar1, Bar2], Foo2=[Baz]}
If you are sure that there are no duplicates, you can use toMap(keyMapper,valueMapper)
method with two parameters:
List<String[]> list = List.of(
new String[]{"Foo1", "Bar1"},
new String[]{"Foo2", "Baz"});
Map<String, String> map2 = list.stream()
.collect(Collectors.toMap(e -> e[0], e -> e[1]));
System.out.println(map2);
// {Foo1=Bar1, Foo2=Baz}
Anyway you can collect a list of Map.Entry
s:
List<String[]> list = List.of(
new String[]{"Foo1", "Bar1"},
new String[]{"Foo1", "Bar2"},
new String[]{"Foo2", "Baz"});
List<Map.Entry<String, String>> list1 = list.stream()
.map(arr -> Map.entry(arr[0], arr[1]))
.collect(Collectors.toList());
System.out.println(list1);
// [Foo1=Bar1, Foo1=Bar2, Foo2=Baz]
See also: Ordering Map<String, Integer> by List<String> using streams
Upvotes: 0
Reputation: 97150
There's no point in creating an intermediate stream and then using flatMap()
.
You can just collect()
directly into a map:
public Map<Foo, Bar> getMap(List<Foo> rawData) {
return rawData.stream()
.collect(Collectors.toMap(foo -> method1(foo), foo -> method2(foo)));
// OR: Collectors.toMap(this::method1, this::method2);
}
Upvotes: 5