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

lap*_*ots 1 java java-8

我有一个清单triples

List<Triple<String, String, String>> triplets; 
Run Code Online (Sandbox Code Playgroud)

我想分组成这样的地图

Map<Pair<String, String>, String> mapping;
Run Code Online (Sandbox Code Playgroud)

value地图的哪里是三元组的第三个元素。如果发生相同的情况,key它应该覆盖剩余的第三个值。

例如

def triples = [ {a, b, c} ; {a, d, e} ; {a, b, f } ]
// grouping
def map = [ {a,b} : c ; {a, d} : e ]
Run Code Online (Sandbox Code Playgroud)

如何使用Java 8及其grouping在流中做到这一点?

Rav*_*ala 5

这应该可以解决问题:

Map<Pair<String, String>, String> result = triplets.stream()
    .collect(
        Collectors.toMap(
            t -> new Pair(t.getOne(), t.getTwo()),
            Triple::getThree,
            (v1, v2) -> v2
        )
    );
Run Code Online (Sandbox Code Playgroud)

部分对类的示例:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

该类HashMap使用equals方法来唯一地标识关键对象。因此,您首先需要重写equalshashcode方法来显示Pair类对象的逻辑相等性Map

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

更新

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

  • 该死,没想到 `mergeFunction`...这更干净。 (2认同)