为现有Stream添加新值

时间:2022-10-08 19:50:26

Is there is a good way to add a new value to existing Stream? All I can imagine is something like this:

是否有一种向现有Stream添加新值的好方法?我能想象的是这样的:

public <T> Stream<T> addToStream(Stream<T> stream, T elem ) {
    List<T> result = stream.collect(Collectors.toList());
    result.add(elem);
    return result.stream();
}

But I'm looking for something more concise that I can use in lambda expression without verbosity.

但是我正在寻找一些更简洁的东西,我可以在没有冗长的lambda表达中使用它。

Another question appeared when I tried to implement PECS principle:

当我尝试实施PECS原则时出现了另一个问题:

public <T> Stream<? super T> addToStream(Stream<? super T> stream, T elem ) {
    List<? super T> result = stream.collect(Collectors.toList()); //error
    result.add(elem);
    return result.stream();
}

Seems like wildcard doesn't work with Stream.collect and I'm wondering why. Thanks in advance.

看起来像通配符不适用于Stream.collect,我想知道为什么。提前致谢。

3 个解决方案

#1


71  

The question belies an incorrect assumption: that streams actually contain their data. They do not; streams are not data structures, they are a means for specifying bulk operations across a variety of data sources.

这个问题掩盖了一个错误的假设:流实际上包含他们的数据。他们不;流不是数据结构,它们是指定跨各种数据源的批量操作的手段。

There are combinators for combining two streams into one, such as Stream.concat, and factories for creating streams from a set of known elements (Stream.of) or from collections (Collection.stream). So you can combine these if you want to produce a new stream that is the concatenation of the stream you have in hand, along with a new stream describing the new elements.

存在用于将两个流组合成一个的组合器,例如Stream.concat,以及用于从一组已知元素(Stream.of)或从集合(Collection.stream)创建流的工厂。因此,如果要生成一个新流,它是您手头的流的串联,以及描述新元素的新流,您可以将它们组合在一起。

The problem in your PECS example is that you've got three occurrences of ? super T, and you are assuming they describe the same type, but they do not. Each occurrence of a wildcard corresponds to a unique capture, which isn't what you want; you need to give that type variable a name so the compiler knows that the type of the list and the type of the input stream are the same. (Also, don't materialize a collection; that's expensive, and potentially non-terminating if the stream is not finite. Just use concat.) So the answer is: you just got the generics wrong. Here's one way to do it:

您的PECS示例中的问题是您有三次出现?超级T,你假设他们描述的是同一类型,但他们没有。每次出现一个通配符都对应一个唯一的捕获,这不是你想要的;您需要为该类型变量指定名称,以便编译器知道列表的类型和输入流的类型是相同的。 (另外,不要实现集合;这是昂贵的,如果流不是有限的,可能是非终止的。只需使用concat。)所以答案是:你只是弄错了泛型。这是一种方法:

public<T> Stream<T> appendToStream(Stream<? extends T> stream, T element) {
    return Stream.concat(stream, Stream.of(element));
}

You confused yourself with PECS because you were thinking about "inserting" into the stream, when in fact you're consuming from it.

您将自己与PECS混淆了,因为您正在考虑“插入”流,而实际上您正在使用它。

#2


23  

How about

怎么样

return Stream.concat(stream, Stream.of(elem));

this is assuming the original Stream is finite. If it's not, you can concat them in a reversed order.

这假设原始流是有限的。如果不是,您可以按相反的顺序连接它们。

#3


0  

The StreamEx library has appropriate #prepend() and #append() methods. Here's an example how they can be used:

StreamEx库具有适当的#prepend()和#append()方法。以下是如何使用它们的示例:

StreamEx.of("second").prepend("first").append("third").forEach(System.out::println);

An output is as follows:

输出如下:

first
second
third

#1


71  

The question belies an incorrect assumption: that streams actually contain their data. They do not; streams are not data structures, they are a means for specifying bulk operations across a variety of data sources.

这个问题掩盖了一个错误的假设:流实际上包含他们的数据。他们不;流不是数据结构,它们是指定跨各种数据源的批量操作的手段。

There are combinators for combining two streams into one, such as Stream.concat, and factories for creating streams from a set of known elements (Stream.of) or from collections (Collection.stream). So you can combine these if you want to produce a new stream that is the concatenation of the stream you have in hand, along with a new stream describing the new elements.

存在用于将两个流组合成一个的组合器,例如Stream.concat,以及用于从一组已知元素(Stream.of)或从集合(Collection.stream)创建流的工厂。因此,如果要生成一个新流,它是您手头的流的串联,以及描述新元素的新流,您可以将它们组合在一起。

The problem in your PECS example is that you've got three occurrences of ? super T, and you are assuming they describe the same type, but they do not. Each occurrence of a wildcard corresponds to a unique capture, which isn't what you want; you need to give that type variable a name so the compiler knows that the type of the list and the type of the input stream are the same. (Also, don't materialize a collection; that's expensive, and potentially non-terminating if the stream is not finite. Just use concat.) So the answer is: you just got the generics wrong. Here's one way to do it:

您的PECS示例中的问题是您有三次出现?超级T,你假设他们描述的是同一类型,但他们没有。每次出现一个通配符都对应一个唯一的捕获,这不是你想要的;您需要为该类型变量指定名称,以便编译器知道列表的类型和输入流的类型是相同的。 (另外,不要实现集合;这是昂贵的,如果流不是有限的,可能是非终止的。只需使用concat。)所以答案是:你只是弄错了泛型。这是一种方法:

public<T> Stream<T> appendToStream(Stream<? extends T> stream, T element) {
    return Stream.concat(stream, Stream.of(element));
}

You confused yourself with PECS because you were thinking about "inserting" into the stream, when in fact you're consuming from it.

您将自己与PECS混淆了,因为您正在考虑“插入”流,而实际上您正在使用它。

#2


23  

How about

怎么样

return Stream.concat(stream, Stream.of(elem));

this is assuming the original Stream is finite. If it's not, you can concat them in a reversed order.

这假设原始流是有限的。如果不是,您可以按相反的顺序连接它们。

#3


0  

The StreamEx library has appropriate #prepend() and #append() methods. Here's an example how they can be used:

StreamEx库具有适当的#prepend()和#append()方法。以下是如何使用它们的示例:

StreamEx.of("second").prepend("first").append("third").forEach(System.out::println);

An output is as follows:

输出如下:

first
second
third