0

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

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

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

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

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

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

重新表述我真正想要的内容:将双for循环转换为使用 Java 8 的语句,很可能涉及Stream.

4

2 回答 2

1

Unfortunately I'm at work and can't install it to actually test this, but if you really want to use Java 8 to fill your 2d array with new Patch instances you can do it like this:

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

If you're bored you can refactor the PatchArrayGenerator class to create any type you want instead of just Patches.

I would definitely stick to the nested loop though :)

于 2014-01-28T21:55:34.800 回答
1

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

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

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

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

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

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

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

另请注意,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()

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

这也许也可以写得更容易,所以欢迎对此发表评论。

于 2014-01-29T07:59:30.790 回答