Feu*_*mel 15 java functional-programming java-8 java-stream
为了这个例子,让我们假设我有一个Tuple带有两个属性的简单类型:
interface Tuple<T, U> {
T getFirst();
U getSecond();
}
Run Code Online (Sandbox Code Playgroud)
现在我想将一个(first, second)元组集合转换为一个映射,该映射将每个first值映射到second具有该特定first值的元组中包含的所有值的集合.该方法groupSecondByFirst()显示了我想要的可能实现:
<T, U> Map<T, Set<U>> groupSecondByFirst(Set<Tuple<T, U>> tuples) {
Map<T, Set<U>> result = new HashMap<>();
for (Tuple<T, U> i : tuples) {
result.computeIfAbsent(i.getFirst(), x -> new HashSet<>()).add(i.getSecond());
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
如果输入是[(1, "one"), (1, "eins"), (1, "uno"), (2, "two"), (3, "three")]输出的话{ 1 = ["one", "eins", "uno"], 2 = ["two"], 3 = ["three"] }
我想知道是否以及如何使用流框架实现这一点.我得到的最好的是以下表达式,它返回一个包含完整元组作为值的映射,而不仅仅是它们的second元素:
Map<T, Set<Tuple<T, U>>> collect = tuples.stream().collect(
Collectors.groupingBy(Tuple::getFirst, Collectors.toSet()));
Run Code Online (Sandbox Code Playgroud)
Feu*_*mel 38
我找到了解决方案; 它涉及Collections.mapping(),它可以包装一个收集器并在流上应用映射函数,以便为包装的收集器提供元素:
static <T, U> Map<T, Set<U>> groupSecondByFirst(Collection<Tuple<T, U>> tuples) {
return tuples
.stream()
.collect(
Collectors.groupingBy(
Tuple::getFirst,
Collectors.mapping(
Tuple::getSecond,
Collectors.toSet())));
}
Run Code Online (Sandbox Code Playgroud)