【问题标题】:Is there a Java method that fills a List by calling a function many times?是否有通过多次调用函数来填充 List 的 Java 方法?
【发布时间】:2015-04-26 15:29:48
【问题描述】:

标准库中有这样的东西吗?它通过调用source.get() 填充List<T>

public static <T> List<T> listFromFunc(int size, Supplier<T> source) {
    return IntStream.range(0, size)
            .mapToObj(i -> source.get())
            .collect(Collectors.toList());
}

【问题讨论】:

    标签: java collections functional-programming java-8


    【解决方案1】:

    恐怕不会,但您可以使用此构造提高代码的可读性

    Stream.generate(source).limit(size).collect(Collectors.toList())
    

    虽然 Brian Goetz mentioned 您的原始版本会更好地并行化。

    【讨论】:

    • 另一方面,问题中的示例(使用 IntStream.range)并行化 much 更好。
    • @BrianGoetz 这很有趣。你能添加一些关于这个主题的更多信息(可能是链接)吗?
    • limit() 操作的语义与遇到的顺序相关联,而这种耦合结果是对并行性的重大限制。举个例子,想象一下并行实现findFirst vs findAny;应该清楚的是后者会更好地并行化(因为一旦找到答案,您就不必等待所有早期元素完成。)另一方面,范围分割完美,因此工作将干净地分布跨核心。
    • @BrianGoetz 谢谢。现在说得通了。我只是对IntStream.range返回StreamSupport.intStream(new Streams.RangeIntSpliterator(..), false)这一事实感到困惑,其中false表示返回的流不会是并行的(看来我需要阅读一些关于Java 8的书才能完全理解它的魔力:))。
    • 它返回一个顺序流,但您可以使用IntStream.range(...).parallel() 将该流并行化,生成的流将并行化得非常好。并非所有管道都可以很好地并行化;那些包含遇到顺序约束的操作(例如,limit、findFirst);那些源拆分不佳的(例如,LinkedList、Stream.iterate、那些从迭代器派生的)等。很难给出一个快速的解码器图表,因为并行性能可能会受到流源、中间操作和终端操作的影响,但是limit 是最严重的违规者之一。
    【解决方案2】:

    这是另一个变体:

    static <T> List<T> listFromFunc(int size, Supplier<T> source) {
        return Collections.nCopies(size, "").stream()
            .map(o -> source.get())
            .collect(Collectors.toCollection(() -> new ArrayList<>(size)));
    }
    

    这使得流始终是SIZEDCollections.nCopies().stream() 实际上在内部使用 IntStream.range(),所以它并没有更快或任何东西。

    使用Collectors.toCollection() 可以控制列表的具体类型,toList() 不能。在顺序情况下,这还允许您预先确定列表的大小,避免在将元素添加到列表时可能发生的复制。

    (公平警告:在 JDK 8 中,toList() 创建了一个 ArrayList,但我们可能会在 JDK 9 中更改它以返回更易于附加的列表类型。)

    【讨论】:

    • Collections.nCopies(size, source).stream().map(Supplier::get)...
    • @Holger 哈!是的,非常有趣的变化!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-07-05
    • 1970-01-01
    • 2022-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-04
    相关资源
    最近更新 更多