【问题标题】:Java Lazy Stream of Strings including List<String>Java 惰性字符串流,包括 List<String>
【发布时间】:2016-08-24 17:23:10
【问题描述】:

我正在懒惰地为前两个简单项目创建一个字符串流。但是,我的流的一部分是字符串列表。

Stream<String> streamA = Stream.concat(
      Stream.generate(item::getStringA),
      Stream.generate(item::getStringB))

return Stream.concat(streamA, item.getStringList(param).stream())

上述方法有效,但 .getStringList 也需要延迟调用。我不清楚如何获取它并将其与流的其余部分“合并”。

【问题讨论】:

    标签: java list java-stream lazy-evaluation


    【解决方案1】:

    我想,你真正想做的是

    return Stream.<Supplier<Stream<String>>>of(
        () -> Stream.of(item.getStringA()),
        () -> Stream.of(item.getStringB()),
        () -> item.getStringList(param).stream())
        .flatMap(Supplier::get);
    

    这会产生一个完全懒惰的Stream&lt;String&gt;,例如.limit(0).count() 不会调用item 上的任何方法或.findFirst() 只会调用getStringA() 等。

    流的 content 将等同于

    Stream.concat(
        Stream.of(item.getStringA(), item.getStringB()), item.getStringList(param).stream())
    

    【讨论】:

    • findFirst() 正是我想要的。虽然 Louis 的回答有效,但我觉得这至少对“流媒体新手”来说更直观。
    【解决方案2】:

    我认为这一切都不会像您认为的那样。 Stream.generate always 生成一个 infinite 流。但最接近你想要的东西就是

    StreamSupport.stream(() -> item.getStringList(param).spliterator(), 0, false)
    

    ...它将懒惰地调用item.getStringList(param)。 (你想要的并不是Stream 的真正预期用例,所以它没有得到很好的支持。)

    【讨论】:

    • 我开始意识到我离我有多远。但是,我认为我永远不会找到 StreamSupport 方法。看起来流很适合我正在做的事情,但使用这种方法似乎有点生硬。
    • 请注意,StreamSupport.stream(Supplier…) 会将调用推迟到终端操作开始时,但将流传递给 Stream.concat 已经具有终止流的效果。所以它并不像你想象的那么懒惰。此外,您永远不应该将0 之类的任意特征传递给它。规范明确指出,特性必须与拆分器的特性相同,因此在使用此方法时,您应该准确地知道自己在做什么。当源是List 时,它们必须至少包含ORDERED | SIZED | SUBSIZED
    【解决方案3】:

    你可以做的是从你的item.getStringList()返回一个Stream

    public static void main(String[] args) throws InterruptedException {
        Item item = new Item();
        Stream<String> a = Stream.concat(Stream.of("A"), Stream.of("B"));
    
        Stream<String> anotherStream = Stream.concat(a, item.getStringList());
    
    
        anotherStream.forEach(System.out::println);
    }
    
    private static class Item {
    
        public Stream<String> getStringList() {
            List<String> l = new ArrayList<>();
    
            l.add("C");
            l.add("D");
            l.add("E");
            l.add("F");
            final AtomicInteger i = new AtomicInteger(0);
            return Stream.iterate(l.get(i.get()), (f) -> {
                // Proof of laziness
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                return l.get(i.getAndIncrement());
            })
            // Iterate is by default unbound
            .limit(l.size());
        }
    }
    

    我不确定这种方法是否仍然有用,因为您的列表仍在记忆中。

    【讨论】:

      猜你喜欢
      • 2012-12-16
      • 1970-01-01
      • 2013-03-14
      • 1970-01-01
      • 1970-01-01
      • 2016-06-20
      • 2012-04-06
      • 2018-11-26
      • 1970-01-01
      相关资源
      最近更新 更多