为现有Stream添加新值

Dmy*_*tro 74 java wildcard java-8

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

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

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

当我尝试实施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();
}
Run Code Online (Sandbox Code Playgroud)

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

Bri*_*etz 91

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

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

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

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

你把自己与PECS混淆了,因为你正在考虑"插入"到流中,而实际上你正在消费它.

  • 该方法不应该命名为"appendToStream"?否则我认为应该切换concat方法的参数. (7认同)

Era*_*ran 33

怎么样

return Stream.concat(stream, Stream.of(elem));
Run Code Online (Sandbox Code Playgroud)

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


art*_*spb 5

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

StreamEx.of("second").prepend("first").append("third").forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

输出如下:

first
second
third
Run Code Online (Sandbox Code Playgroud)