【发布时间】:2021-10-22 09:24:46
【问题描述】:
我是函数式编程的新手,我正在努力变得更好。
目前,我正在试验一些采用以下基本形式的代码:
private static int myMethod(List<Integer> input){
Map<Integer,Long> freq = input
.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()));
return (int) freq
.keySet()
.stream()
.filter(key-> freq.containsKey(freq.get(key)))
.count();
}
首先使用哈希图来获取列表中每个数字的频率。接下来,我们总结了在地图中也作为键存在的键的数量。
我不喜欢两个流需要彼此分开存在的方式,其中 HashMap 是由一个流制成的,只是为了立即被另一个流专门使用。
有没有办法将它组合成一个流?我在想这样的事情:
private static int myMethod(List<Integer> input){
return (int) input
.stream()
.collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.keySet()
.stream()
.filter(key-> freq.containsKey(freq.get(key)))
.count();
}
但这里的问题是没有可参考的频率映射,因为它被用作管道的一部分,因此过滤器无法完成它需要做的事情。
总之,我不喜欢这样收集到一个哈希图然后再转换回一个键集。有没有办法“简化”(双关语)这个操作来
- 不会在流和 hashmap 之间来回切换
- 以某种方式引用自身,而无需在管道之前声明单独的映射。
谢谢!
【问题讨论】:
-
您的建议应该有效。但是,我在您的建议中看到了一个问题。你在哪里获取频率来检索密钥?
-
Freq 不存在,这是代码示例 2 中的问题。我不知道是否有自我引用的方法,如果没有 - 那么 freq 必须像代码示例中一样单独声明1.
-
你可以使用
collectingAndThen(),但不会更漂亮。 -
只是为了确保我得到你是这个 .filter(key-> freq.containsKey(freq.get(key)) 来检查值是否等于其中一个键或者我错过了了解一下
-
这永远不会是真的:
freq.containsKey(freq.get(key))。freq.get(key)返回一个Long,映射的键是Integer。Long对象永远不会等于Integer对象(原始long可能等于原始int,但这是另一回事)。
标签: java functional-programming java-stream