使用pair键将三元组列表分组到映射中



我有一个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方法来唯一地标识关键对象。因此,您首先需要重写equalshashcode方法,以显示Map类的Pair对象的逻辑相等性。

然后返回到流和lambda。对于每个三元组,使用Collectors.toMap,其中Pair对象作为关键字,Triplet的另一个剩余值作为值。然后提供一个mergeFunction来处理密钥冲突。在您的情况下,您需要保留以前的值,同时丢弃新值。这就是你所需要做的。

更新

我已经根据以下评论更新了合并功能。

如果您想使用Collectors.groupingBy,可以将其与下游mappingreducingCollectors:组合使用

@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(值。

最新更新