4

让我们考虑一下我有以下课程:

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 on Stream。其次,编译器无法确定返回类型的类型。它认为它 List<Object>而不是预期的List<A>。我该如何解决?

4

2 回答 2

6

一种使用方法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)……更好。</p>


一种替代方法是使用真正的展平操作而不是嵌套操作:

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());

我看到的主要缺点是它缺少IntPairorTuple<int,int>类型。因此,它使用数组作为解决方法。

于 2015-01-06T16:54:20.390 回答
1

如果可以有可变变量,您可以像这样获得 A 类的列表....

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());
于 2015-01-06T16:32:51.033 回答