通过Streams调用双数组上的构造函数

时间:2014-01-28 21:33:51

标签: java arrays constructor java-8 java-stream

我想知道Java 8是否可以实现以下功能:

Patch[][] patches = new Patch[width][depth];

我想使用Stream来调用构造函数,我知道有Arrays.stream(patches)可以给我一个Stream<Patch[]>,所以不幸的是我认为没有任何用处(但是在我的想法中。)

在旧的Java中,这可以归结为简单:

for (int w = 0; w < width; w++) {
    for (int z = 0; z < depth; z++) {
        patches[w][z] = new Patch();
    }
}

最有用的方法是将T[][]破坏为Stream<T>我认为的方法。

重新说明我真正想要的内容:将双for - 循环转换为使用Java 8的语句,最有可能涉及Stream

2 个答案:

答案 0 :(得分:1)

不幸的是我正在工作并且无法安装它来实际测试它,但是如果你真的想用Java 8用新的Patch实例填充你的2d数组,你可以这样做:< / p>

import java.util.function.IntFunction;

public class PatchArrayGenerator implements IntFunction<Patch[]>
{
    private final int depth;

    public PatchArrayGenerator(int depth)
    {
        this.depth = depth;
    }

    public Patch[] apply(int value)
    {
        Patch[] patchArray = new Patch[depth];
        Arrays.parallelSetAll(patchArray, value -> new Patch());
        return patchArray;
    }
}

public class PatchMaker
{     
    public static void main(String... args)
    {
        int depth = 5, width = 5;
        Patch[][] patches = new Patch[width][depth];
        Arrays.parallelSetAll(patches, new PatchArrayGenerator(depth));
    }
}

如果您感到无聊,可以重构PatchArrayGenerator类来创建您想要的任何类型,而不仅仅是补丁。

我肯定会坚持使用嵌套循环:)

答案 1 :(得分:1)

在了解了lambda的工作原理之后,我设法让它工作了:

Arrays.stream(patches)
        .forEach(pArray -> Arrays.parallelSetAll(pArray, i -> new Patch()));

首先,我将解释一个更简单的版本:

Object[] test = new Object[10];
Arrays.parallelSetAll(test, i -> new Object());

上一版本的作用是首先分配一个Object[10],一个十Object的数组。然后它使用具有以下签名的新Arrays.parallelSetAll方法之一:

public static <T> void parallelSetAll(T[] array,
                                      IntFunction<? extends T> generator)

在这种情况下,我使用IntFunction<? extends T> generator lambda表达式i -> new Patch(),为new Patch()生成i:在这种情况下,我们不需要虽然i,但我们需要它来构造一个正确的lambda表达式。

另请注意,Object::new无法使用(据我所知),然后会给出消息:

incompatible types: cannot infer type-variable(s) T
    (argument mismatch; bad return type in lambda expression
      Object is not a functional interface)
  where T is a type-variable:
    T extends Object declared in method <T>parallelSetAll(T[],IntFunction<? extends T>)

回到我的问题的实际答案:我在那里做的非常类似于我刚才解释的,除了我有Patch[][]作为输入,我首先需要循环,我通过以下方式完成:

Arrays.stream(patches).forEach(),其签名为:void forEach(Consumer<? super T> action)

然后我在这里使用lambda表达式pArray -> Arrays.parallelSetAll(pArray, i -> new Patch())

这样有效地首先遍历所有Patch[]数组,然后并行将Patch[]的所有元素设置为new Patch()

它是否实际上比双循环更容易是有争议的,但我可以争辩说代码的数量至少相同,并且可能更容易键入,因为不需要输入,额外的花括号等。

这也许可以写得更容易,所以欢迎提出意见。