我有一个键-值对列表,我想过滤每个键参数只出现一次的列表。
使得例如{Pair(1,2), Pair(1,4), Pair(2,2)}
的列表变为{Pair(1,2), Pair(2,2)}
。
哪个Pair
被过滤掉并不重要,因为我只需要大小(也许有一种不同的方法来获得成对不同键值的对的数量?)。
这一切都发生在另一个列表数组(键-值对)的流中,它们都被加起来了。
我想要的是hashmap中碰撞的数量
我希望你明白我的意思;如果没有,请询问。
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();
}
编辑: 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();
}
如果密钥相同,我覆盖了Pair的等号以返回true,所以现在我可以使用distinct来删除"重复项"(具有相同密钥的对)。是否有可能,在forEach中,用相同的列表"distinct"替换currentElement ?如果有,怎么做?
问候,Claas M
我不确定你是否想要每个列表的碰撞量的总和或所有列表的碰撞量被合并成一个单一的之前。我假设是前者,但如果是后者,这个想法也没有太大变化。
你可以这样做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)
将给你一个Stream<List<List<Pair<Integer, Integer>>
与一个单一的元素。然后flatMap
,得到Stream<List<Pair<Integer, Integer>>
。
从那里,你mapToInt
每个列表的原始大小减去唯一的元素对的键数它包含(l.stream().map(p -> p.k).distinct().count()
)。
最后,调用sum来获得碰撞的总数量。
请注意,您可以使用mapToLong
来摆脱强制转换,但collisions
必须是long
(如果每个列表有很多"碰撞",这可能更正确)。
例如给定输入:
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);
它将输出4,因为在第一个列表中有1个碰撞,在第二个列表中有1个,在第三个列表中有2个。
不要使用流。将列表转储到带有自定义比较器的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();
如果键类型不可比较,则相应地更改比较器lambda