让我们考虑一下我的课程:
class A {
int i, j, k;
public A(int i, int j, int k) {
this.i = i; this.j = j; this.k = k;
}
}
其中i
,j
,k
具有已知范围:r_i
,r_j
,r_k
。现在我想生成
此范围内A
的所有可能实例。我可以想出类似的东西:
Stream.iterate(0, n -> ++n).limit(r_i)
.flatMap(i -> Stream.iterate(0, n -> ++n).limit(r_j)
.flatMap(j -> Stream.iterate(0, n -> ++n).limit(r_k)
.map(k -> new A(i, j, k)))).collect(Collectors.toList())
首先,它太冗长了。有没有办法缩短它?特别是我找不到range
在Stream
。其次,编译器无法确定返回类型的类型。它认为是
List<Object>
代替预期的List<A>
。我该如何解决这个问题?
答案 0 :(得分:5)
使用range
的一种方法是立即执行拳击转换:
List<A> list=IntStream.range(0, r_i).boxed()
.flatMap(i -> IntStream.range(0, r_j).boxed()
.flatMap(j -> IntStream.range(0, r_k)
.mapToObj(k -> new A(i, j, k)))).collect(Collectors.toList());
这不是最漂亮的代码,但IntStream.range(0, max).boxed()
仍然优于Stream.iterate(0, n -> n+1).limit(max)
......
一种替代方法是使用实际展平操作而不是嵌套操作:
List<A> list=IntStream.range(0, r_i).boxed()
.flatMap(i -> IntStream.range(0, r_j).mapToObj(j -> new int[]{i,j}))
.flatMap(ij -> IntStream.range(0, r_k).mapToObj(k -> new A(ij[0], ij[1], k)))
.collect(Collectors.toList());
我看到的主要缺点是它缺少IntPair
或Tuple<int,int>
类型。所以它使用数组作为解决方法。
答案 1 :(得分:1)
如果可以使用可变变量,你可以像这样获得A类的List ....
List<A> newCollect = new ArrayList<>();
IntStream.range(0, r_i).forEach(
i -> IntStream.range(0, r_j).forEach(
j -> IntStream.range(0, r_k).forEach(
k -> newCollect.add(new A(i, j, k))
)
)
);
或者您可以像这样制作A列表列表,然后是flatMap两次......
List<A> newCollect2 = IntStream.range(0, r_i).mapToObj(
i -> IntStream.range(0, r_j).mapToObj(
j -> IntStream.range(0, r_k).mapToObj(
k -> new A(i, j, k)
).collect(Collectors.toList())
).collect(Collectors.toList())
)
.flatMap(a -> a.stream())
.flatMap(a -> a.stream())
.collect(Collectors.toList());