How to implement a Java stream?

杀马特。学长 韩版系。学妹 提交于 2019-12-17 10:58:18

问题


I want to implement a Stream<T>.

I don't want to just use implements Stream<T>, because I would have to implement a ton of methods.

Can this be avoided?

To be more concrete, how can I stream t1, t2 and t3 for example:

class Foo<T> {
    T t1, t2, t3;

    Foo(T t1, T t2, T t3) {
        this.t1 = t1;
        this.t2 = t2;
        this.t3 = t3;
    }
}

回答1:


The JDK's standard implementation of Stream is the internal class java.util.stream.ReferencePipeline, you cannot instantiate it directly.

Instead you can use java.util.stream.Stream.builder(), java.util.stream.StreamSupport.stream(Spliterator<T>, boolean) and various1, 2 other static factory methods to create an instance of the default implementation.

Using a spliterator is probably the most powerful approach as it allows you to provide objects lazily while also enabling efficient parallelization if your source can be divided into multiple chunks.

Additionally you can also convert streams back into spliterators, wrap them in a custom spliterator and then convert them back into a stream if you need to implement your own stateful intermediate operations - e.g. due to shortcomings in the standard APIs - since most available intermediate ops are not allowed to be stateful.
See this SO answer for an example.

In principle you could write your own implementation of the stream interface, but that would be quite tedious.




回答2:


You usually do not need to write your own stream class. Instead you can create stream by existing methods. For instance, here is how to create a stream of the value 1, 100:

  AtomicInteger n = new AtomicInteger(0);
  Stream<Integer> stream = Stream.generate(() -> n.incrementAndGet()).limit(100);

so in here we created an infinite stream of integers: 1, 2, 3, .... then we used limit(100) on that infinite stream to get back a stream of 100 elements.

For clarity, if you want a stream of integers (at fixed intervals) you should use IntStream.range(). This is just an example to show how streams can be defined using Stream.generate() which gives you more flexibility as it allows you to use arbitrary logic for determining steam's elements.




回答3:


If you're wanting to make your own Stream because you want custom close() logic, the simplest solution is to create a Stream from an Iterator, and call onClose(Runnable). For instance, to stream from a Reader via Jackson:

MappingIterator<?> values = objectMapper.reader(type).readValues(reader);
return StreamSupport
        .stream(Spliterators.spliteratorUnknownSize(values, Spliterator.ORDERED), false)
        .onClose(() -> {
            try {
                reader.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });



回答4:


For the sake of completeness, as I did not find this directly among the answers here on SO: If you want to transform an existing Iterator into a Stream (e.g., because you want to generate elements successively), use this:

StreamSupport.stream(
    Spliterators.spliterator(myIterator, /* initial size*/ 0L, Spliterator.NONNULL), 
    /* not parallel */ false);

I found this a bit hard to find, as you need to know StreamSupport, Spliterators and Spliterator




回答5:


Others have answered how to provide a general-purpose Stream implementation. Regarding your specific requirement, just do this:

class Foo<T> {

    T t1, t2, t3;

    Foo(T t1, T t2, T t3) {
        this.t1 = t1;
        this.t2 = t2;
        this.t3 = t3;
    }

    Stream<T> stream() {
        return Stream.of(t1, t2, t3);
    }
}


来源:https://stackoverflow.com/questions/30685623/how-to-implement-a-java-stream

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!