我有一个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
?
这应该可以做到:
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
方法,以显示Map
类的Pair
对象的逻辑相等性。
然后返回到流和lambda。对于每个三元组,使用Collectors.toMap
,其中Pair
对象作为关键字,Triplet
的另一个剩余值作为值。然后提供一个mergeFunction
来处理密钥冲突。在您的情况下,您需要保留以前的值,同时丢弃新值。这就是你所需要做的。
更新
我已经根据以下评论更新了合并功能。
如果您想使用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
,以保持第一次出现。
这里是一个可能的解决方案
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的类型,如果它覆盖等于,就不会有重复,否则它将在地图的密钥中重复
使用映射::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));
这将CCD_ 22列表的元素插入到映射中,其中键是表示CCD_ 23的第一和第二值的一对,并且映射的值是CCD_ 24的第三值。
在密钥冲突的情况下,我们使用重映射函数(o, n) -> o
来保持旧的(o
(值。