【发布时间】:2015-07-31 21:44:18
【问题描述】:
对于一个整数范围,我想应用一个(“昂贵”)操作,只过滤掉那些有有趣答案的整数,然后对答案进行分组。
第一个 sn-p 有效,但它在代码和计算中都重复了操作(“模 2”):
IntStream.range(1, 10).boxed()
.filter(p -> (p % 2 != 0)) // Expensive computation
.collect(Collectors.groupingBy(p -> (p % 2))); // Same expensive
// computation!
// {1=[1, 3, 5, 7, 9]} (Correct answer)
我尝试先映射到答案,然后过滤,然后分组 - 但最初的整数当然会在此过程中丢失:
IntStream.range(1, 10).boxed()
.map(p -> p % 2) // Expensive computation
.filter(p -> p != 0)
.collect(Collectors.groupingBy(p -> p));
// {1=[1, 1, 1, 1, 1]} (Of course, wrong answer)
我想映射到一个元组或类似的东西,但还没有找到一个干净的方法来做到这一点。
【问题讨论】:
-
您能解释一下您要做什么吗?我们唯一的解释是您正在尝试进行“昂贵”的操作(模数对我来说并不是很昂贵,但好的,我会顺其自然)。但是输入是什么,预期输出是什么?
-
可能最好的方法是创建一个小值类(帮助类)来包含原始 int 和昂贵操作的结果。见stackoverflow.com/a/29340148/1441122。
-
为什么?如果您不想两次执行相同的昂贵计算,则需要将其存储在某处,这是通过让自定义类处理这些结果来实现的。您可以使用
int[2]数组,但会丢失一些语义。 -
@Markus 你可以这样做:
IntStream.range(1, 10).mapToObj(p -> new int[]{p, p % 2}).filter(arr -> arr[1] != 0).collect(groupingBy(arr -> arr[1], mapping(arr -> arr[0], toList()))); -
@Juru 好吧,我的回答说明了我的偏好,但我完全愿意接受其他人有不同的偏好。像
Pair<A,B>这样的典型元组需要装箱,并且像int[2]技巧一样,您不能将名称与不同的元素相关联。这些是更喜欢辅助类的原因。但我同意它们冗长而笨重。虽然不确定旧时。 :-)
标签: java functional-programming java-8 java-stream