从对象的方法创建流

时间:2018-07-12 14:53:07

标签: java-8 java-stream

用和对象的方法初始化Stream的最佳方法是什么?

Foo foo1 = new Foo();
Foo foo2 = foo1.getNext();
Foo foo3 = foo2.getNext();

我想要通过getNext()方法的foo,foo1,foo2等流。

我尝试过

Stream.iterate
Stream.generate

但是这些方法会返回无限流。

2 个答案:

答案 0 :(得分:0)

首先想到的是使用limit截断流:

Stream.iterate(foo1, Foo::getNext)
      .limit(size)....

但是很明显,如果大小未知,这是没有用的。

如果大小未知,那么肯定会有某种条件说“停下来,别无所求”。

JDK-9 offers these overloads:

Stream.iterate(foo1, Foo::getNext)
      .takeWhile(f -> someCondition)
      ....  // further intermediate or a terminal operation

或:

Stream.iterate(foo1, f -> someCondition, Foo::getNext)
      .... // further intermediate or a terminal operation

如果您不能使用JDK-9,那么您唯一的选择是创建自己的帮助器方法来执行您要遵循的逻辑。

答案 1 :(得分:0)

问题中未指定它,但是我相信您想在getNext()返回null时停止迭代(这似乎是最有意义的)。

如果是这样,至少有三种方法:

  1. 如果在JDK 9+上,请执行Aominè建议的操作:

    Stream.iterate(foo1, Objects::nonNull, Foo::getNext)
    
  2. 如果在JDK 8上,您不介意引入额外的依赖关系,请使用jOOλ及其iterateWhilePresent方法:

    Seq.iterateWhilePresent(foo1, foo -> Optional.ofNullable(foo.getNext))
    
  3. 如果在JDK 8上并且您不想要引入额外的依赖关系,请编写一个使用自定义Spliterator的方法,例如(请注意,这不是急切地调用generator的最有效的实现):

    public static <T> Stream<T> iterateUntilNull(T seed, UnaryOperator<T> generator) {
        Spliterator<T> spliterator = new Spliterator<T>() {
            private T next = seed;
    
            @Override
            public boolean tryAdvance(Consumer<? super T> action) {
                if (next == null) {
                    return false;
                }
                action.accept(next);
                next = generator.apply(next);
                return true;
            }
    
            @Override
            public Spliterator<T> trySplit() {
                return null;
            }
    
            @Override
            public long estimateSize() {
                return Long.MAX_VALUE;
            }
    
            @Override
            public int characteristics() {
                return Spliterator.NONNULL;
            }
        };
        return StreamSupport.stream(spliterator, false);
    }
    

    然后致电:

    iterateUntilNull(foo1, Foo::getNext)