Подтвердить что ты не робот

Как реализовать поток Java?

Я хочу реализовать Stream<T>.

Я не хочу просто использовать implements Stream<T>, потому что мне пришлось бы реализовать тонну методов.

Можно ли этого избежать?

Чтобы быть более конкретным, как я могу передать t1, t2 и t3, например:

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

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

Ответ 1

Стандартная реализация JQK Stream - это внутренний класс java.util.stream.ReferencePipeline, вы не можете его напрямую создать.

Вместо этого вы можете использовать java.util.stream.Stream.builder(), java.util.stream.StreamSupport.stream(Spliterator <T>, boolean) и различные 2 другие статические методы factory для создания экземпляра реализации по умолчанию.

Использование spliterator, вероятно, является самым мощным подходом, поскольку он позволяет вам ленизировать объекты, а также обеспечивает эффективную распараллеливание, если ваш источник можно разделить на несколько кусков.

Кроме того, вы также можете конвертировать потоки обратно в разделители, обернуть их в пользовательский разделитель и затем преобразовать их обратно в поток, если вам нужно реализовать свои собственные промежуточные операции с промежуточным состоянием - например. из-за недостатков в стандартных API-интерфейсах - поскольку большинство доступных промежуточных операций не разрешено сохранять состояние. См. этот ответ SO для пример.

В принципе вы могли бы написать свою собственную реализацию интерфейса потока, но это было бы довольно утомительно.

Ответ 2

Обычно вам не нужно писать собственный класс потока. Вместо этого вы можете создавать поток существующими методами. Например, вот как создать поток значения 1, 100:

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

поэтому здесь мы создали бесконечный поток целых чисел: 1, 2, 3,.... тогда мы использовали limit(100) для этого бесконечного потока, чтобы вернуть поток из 100 элементов.

Для ясности, если вы хотите поток целых чисел (с фиксированными интервалами), вы должны использовать IntStream.range(). Это просто пример, показывающий, как потоки могут быть определены с помощью Stream.generate(), что дает вам большую гибкость, поскольку позволяет использовать произвольную логику для определения элементов пара.

Ответ 3

Если вы хотите создать свой собственный поток, потому что вам нужна пользовательская логика close(), самым простым решением является создание потока из итератора и вызов onClose(Runnable). Например, для потока из Reader через Джексон:

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

Другие ответили, как обеспечить реализацию универсального Stream. Что касается вашего конкретного требования, просто выполните следующее:

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);
    }
}

Ответ 5

Для полноты, поскольку я не нашел это прямо среди ответов здесь на SO: Если вы хотите преобразовать существующий Iterator в поток (например, потому что вы хотите генерировать элементы последовательно), используйте это:

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

Я нашел это немного сложно найти, так как вам нужно знать StreamSupport, Spliterators и Spliterator