Java 8使用Supplier填充数组

26

有没有一种使用Java 8的Supplier来填充数组的方法?

我想要编写:

Supplier<Object> supplier = () -> new Object();
Object[] array = new Object[size];
Arrays.fill(array, supplier);

注意: 我知道我可以编写自己的方法。

4个回答

36
如果您想要创建一个由Supplier生成结果填充的新数组,可以使用以下方法。
Object[] array = Stream.generate(supplier)
                       .limit(arraySize)
                       .toArray(); // will generate new *Object[]* array

对于不同类型,您可以使用toArray(IntFunction<YourType[]> generator);,例如toArray(YourType[]::new)致谢 @Holger)。

String[] array  = Stream.generate(supplier)
                        .limit(10)
                        .toArray(String[]::new); //now *String[]* array will be returned

Streams还允许我们处理大多数“流行”的基本类型,包括intlongdouble。例如,我们可以使用IntStream#toArray创建int[],其中包含来自IntStream的元素。要从供应商中获取元素并将其“填充”到IntStream中,我们可以使用IntStream.generate(intSupplier)
int[] array = IntStream.generate(()->1)
                       .limit(5)
                       .toArray(); //returns `new Int[]{1,1,1,1,1}

如果您想要用供应商的数据填充已存在的数组,请参考Stuart Marks发布的answer,基于Arrays.setAll(array, supplier),除了处理对象数组外,还支持一些原始类型的数组:double[]int[]long[]

另一种选择是使用@Hogler'scomment中提出的创造性解决方案:

Arrays.asList(array).replaceAll(x -> supplier.get()); 
//you can even overwrite a range using `subList`

请注意,Arrays.asList 的设计是用于处理引用类型(非基本类型)的数组,因此它将不能正确处理像Jon Skeet在答案https://dev59.com/R3M_5IYBdhLWcg3wPAdF#1467940中所解释的那样的int[]数组。


谢谢,这非常接近我想要的。我用Object给出了我的示例,但如果我想使用另一种类型,比如IntegerDate,该怎么办? - gontard
5
要生成一个 MyType 数组,请使用 toArray(MyType[]::new) - Holger
好的。你能在你的回答中加入这个备选方案吗?最后一个问题:是否可以使用通用类型完成相同的操作?我知道不能创建通用数组,但是也许…… - gontard
3
可以采用以下“创意”方式填充已有的数组:Arrays.asList(array).replaceAll(x->supplier.get());。还可以使用 subList 覆盖一定范围内的元素。 - Holger
使用创造性的方式时,应注意原始类型。第一个示例是可以的: System.out.println(Arrays.asList( new Integer[]{1,2,3,4,5})); [1, 2, 3, 4, 5]第二个示例是包含一个单一元素的列表,该元素是整个数组: System.out.println(Arrays.asList( new int[]{1,2,3,4,5})); [[I@53b32d7] - Norbert Madarász

31
java.util.Arrays 中有一个方法
<T> void Arrays.setAll(T[] array, IntFunction<T> generator)

这里不需要供应商,而是需要一个IntFunction,其输入参数是正在填充的数组索引。如果您的对象不依赖于目标数组索引,则可以忽略该参数并像这样调用供应商:

Arrays.setAll(array, i -> supplier.get());

数组的重载适用于基本类型和引用类型的数组。还有一组对应的方法parallelSetAll(),可以并行执行相同的操作(它在内部使用流实现)。


如果这个方法有一个重载版本,最后一个参数是Supplier<T>而不是IntFunction的话,那将会非常美妙。 - Dawood ibn Kareem

0

你可以轻松地编写自己的代码:

public static <T> void fillArray(T[] array, Supplier<? extends T> supplier) {
    for(int k = 0; k < array.length; k++)
        array[k] = supplier.get();
}

谢谢,但我在提问时应该更加具体。我知道我可以用Java编写方法。 - gontard

-1

除了Pshemo的解决方案,您还可以使用map方法。

Object[] array = new Object[size];
array = Arrays.stream(array).map(a -> new Object()).toArray();

@Pshemo:我明白了。我以为他想要一个带有相同对象的常规填充。 - Syam S
在这个解决方案中,数组被创建了两次。 - Timofey Gorshkov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接