我有一个triples
List<Triple<String, String, String>> triplets;
我想分组成这样的地图
Map<Pair<String, String>, String> mapping;
地图的value
处的位置是三元组的第三个元素。并且如果使用相同的key
,则它应覆盖剩余的第三个值。
例如
def triples = [ {a, b, c} ; {a, d, e} ; {a, b, f } ]
// grouping
def map = [ {a,b} : c ; {a, d} : e ]
如何在流中使用Java 8
及其grouping
?
答案 0 :(得分:4)
这应该可以解决问题:
Map<Pair<String, String>, String> result = triplets.stream()
.collect(
Collectors.toMap(
t -> new Pair(t.getOne(), t.getTwo()),
Triple::getThree,
(v1, v2) -> v2
)
);
部分配对类的示例:
public class Pair<T, U> {
//...
@Override
public int hashCode() {
return one.hashCode() + two.hashCode();
}
@Override
public boolean equals(Object obj) {
if (!(obj instanceof Pair))
return false;
Pair p = (Pair) obj;
return p.one.equals(one) && p.two.equals(two);
}
}
HashMap
类使用equals
方法来唯一地标识关键对象。因此,您首先需要重写equals
和hashcode
方法以显示Pair
类的Map
对象的逻辑相等性。
然后回到小溪和lambda。对于每个三元组,请使用Collectors.toMap
,将Pair
对象作为键,并将Triplet
的其他剩余值用作值。然后提供mergeFunction
来处理键冲突。在您的情况下,您需要保留先前的值,而丢弃新的值。这就是您要做的全部。
更新
我已根据以下注释更新了合并功能。
答案 1 :(得分:1)
如果要使用Collectors.groupingBy
,可以将其与下游mapping
和reducing
Collectors
组合:
@Data @AllArgsConstructor
class Triple {
String x, y ,z;
}
@Data @AllArgsConstructor
class Pair {
String x, y;
}
List<Triple> lst = List.of(new Triple("a", "b", "c"),
new Triple("a", "d", "e"),
new Triple("a", "b", "f"));
Map<Pair, String> map = lst.stream()
.collect(Collectors.groupingBy(t -> new Pair(t.x, t.y),
Collectors.mapping(t -> t.z,
Collectors.reducing(null, (x,y) -> y))));
// {Pair(x=a, y=b)=f, Pair(x=a, y=d)=e}
您也可以将(x,y) -> y
更改为(x,y) -> x
,以保持第一次出现。
答案 2 :(得分:0)
这里可能的解决方案
String[] l1=new String[]{"a", "b", "c"};
String[] l2={"a", "d", "e"};
String[] l3={"a", "b", "c"};
List<String[]> t=new ArrayList<>();
t.add(l1);
t.add(l2);
t.add(l3);
Map<String[],String> m=t.stream().
collect(Collectors.toMap(x->new String[]{x[0],x[1]}, x->x[2],(x,y)->x));
但是取决于 Triple 的类型,如果它覆盖等于,则不会重复,否则将在映射的键中重复
答案 3 :(得分:0)
使用Map::merge:
Map<Pair<String, String>, String> result = new HashMap<>();
triplets.forEach(e -> result.merge(new Pair<>(e.getOne(), e.getThree()), e.getThree(), (o, n) -> o));
这会将triplets
列表的元素插入到映射中,其中的键是一对,分别表示Triple
的第一个和第二个值,映射的值是{的第三个值{1}}。
在发生键冲突的情况下,我们使用重映射函数Triple
来维持旧的((o, n) -> o
)值。