简体   繁体   English

Java列表:使用lambda表达式获取成对的具有成对的不同键的对

[英]Java list: get amount of Pairs with pairwise different Keys using lambda expressions

I have a list of key-value-pairs and I want to filter a list where every key parameter only occurs once. 我有一个键-值对列表,我想过滤一个列表,其中每个键参数仅出现一次。

So that a list of eg {Pair(1,2), Pair(1,4), Pair(2,2)} becomes {Pair(1,2), Pair(2,2)} . 因此,例如{Pair(1,2), Pair(1,4), Pair(2,2)}将成为{Pair(1,2), Pair(2,2)}

It doesn't matter which Pair gets filtered out as I only need the size (maybe there's a different way to get the amount of pairs with pairwise different key values?). 筛选出哪个Pair并不重要,因为我只需要大小即可(也许有一种不同的方法来获取具有成对的不同键值的对的数量?)。

This all is again happening in another stream of an array of lists (of key-value-pairs) and they're all added up. 所有这一切再次在(键值对的)列表数组的另一个流中发生,并且它们全部加在一起。

I basically want the amount of collisions in a hashmap. 我基本上想要哈希映射中的冲突量。

I hope you understand what I mean; 我希望你明白我的意思; if not please ask. 如果没有,请询​​问。

public int collisions() {
    return Stream.of(t)
            .filter(l -> l.size() > 1)
            .filter(/*Convert l to list of Pairs with pairwise different Keys*/)
            .mapToInt(l -> l.size() - 1)
            .sum();
}

EDIT: 编辑:

    public int collisions() {
    return Stream.of(t)
            .forEach(currentList = stream().distinct().collect(Collectors.toList())) //Compiler Error, how do I do this?
            .filter(l -> l.size() > 1)
            .mapToInt(l -> l.size() - 1)
            .sum();
}

I overwrote the equals of Pair to return true if the Keys are identical so now i can use distinct to remove "duplicates" (Pairs with equal Keys). 我重写了Pairs的等号,如果Keys相同,则返回true,所以现在我可以使用distinct来删除“重复项”(具有相同Keys的对)。 Is it possible to, in forEach, replace the currentElement with the same List "distincted"? 在forEach中,是否可以用相同的“区别”列表替换currentElement? If so, how? 如果是这样,怎么办?

Regards, Claas M 问候,克拉斯M

Don't use a stream. 不要使用流。 Dump the list into a SortedSet with a custom comparator and diff the sizes: 使用自定义比较器将列表转储到SortedSet中,并比较大小:

List<Pair<K, V>> list; // given this

Set<Pair<K, V>> set = new TreeSet<>(list, (a, b) -> a.getKey().compareTo(b.getKey())).size();
set.addAll(list);
int collisions = list.size() - set.size();

If the key type isn't comparable, alter the comparator lambda accordingly. 如果密钥类型不可比,则相应地更改比较器的lambda值。

I'm not sure whether you want the sum of amount of collisions per list or the amount of collisions in all list were merged into a single one before. 我不确定您是希望将每个列表的冲突总数之和还是将所有列表中的冲突总数合并为一个。 I assumed the former, but if it's the latter the idea does not change by much. 我以为是前者,但是如果是后者,这个想法不会有太大变化。

This how you could do it with Streams : 这样,您可以使用Streams做到这一点:

int collisions = Stream.of(lists)
                       .flatMap(List::stream)
                       .mapToInt(l -> l.size() - (int) l.stream().map(p -> p.k).distinct().count())
                       .sum();

Stream.of(lists) will give you a Stream<List<List<Pair<Integer, Integer>> with a single element. Stream.of(lists)将为您提供一个带有单个元素的Stream<List<List<Pair<Integer, Integer>> Then you flatMap it, so that you have a Stream<List<Pair<Integer, Integer>> . 然后,对它进行flatMap处理,以便获得Stream<List<Pair<Integer, Integer>>

From there, you mapToInt each list by substracting its original size with the number of elements of unique Pairs by key it contained ( l.stream().map(p -> pk).distinct().count() ). 从那里,您可以通过mapToInt每个键的唯一对的元素数减去其原始大小来mapToInt每个列表( l.stream().map(p -> pk).distinct().count() )来l.stream().map(p -> pk).distinct().count()每个列表。

Finally, you call sum to have the overall amount of collisions. 最后,您调用sum以获得碰撞的总数。

Note that you could use mapToLong to get rid of the cast but then collisions has to be a long (which is maybe more correct if each list has a lot of "collisions"). 请注意,您可以使用mapToLong摆脱mapToLong转换,但是collisions必须很long (如果每个列表都有很多“冲突”,则可能更正确)。

For example given the input: 例如,给定输入:

List<Pair<Integer, Integer>> l1 = Arrays.asList(new Pair<>(1,2), new Pair<>(1,4), new Pair<>(2,2));
List<Pair<Integer, Integer>> l2 = Arrays.asList(new Pair<>(2,2), new Pair<>(1,4), new Pair<>(2,2));
List<Pair<Integer, Integer>> l3 = Arrays.asList(new Pair<>(3,2), new Pair<>(3,4), new Pair<>(3,2));

List<List<Pair<Integer, Integer>>> lists = Arrays.asList(l1, l2, l3);

It will output 4 as you have 1 collision in the first list, 1 in the second and 2 in the third. 当第一个列表中有1个碰撞,第二个列表中有1个碰撞,第三个列表中有2个碰撞时,它将输出4。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM