为现有流添加新价值


78

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

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

但我正在寻找可以在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();
}

似乎通配符不起作用Stream.collect,我想知道为什么。提前致谢。


2
不能保证Listcollect(Collectors.toList())supports返回add,您可以使用Collectors.toCollection来选择您得到的列表的类型。
亚历克斯-GlassEditor.com 2015年

Answers:


97

问题在于一个错误的假设:流实际上包含其数据。他们不; 流不是数据结构,它们是用于指定跨各种数据源的批量操作的一种方式。

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

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

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

您将自己与PECS混淆了,因为您实际上正在考虑“插入”到流中,而实际上却是从流中进行消费。


7
该方法不应该命名为“ appendToStream”吗?否则我认为应该切换concat方法的参数。
Andrea Polci '16

concat该方法可以从javadoc中使用,但不能太多:从重复级联构造流时,请谨慎使用。访问深度串联流的元素可能会导致深度调用链,甚至导致StackOverflowException。
TongChen

34

怎么样

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

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


从重复级联构造流时请谨慎。访问深度串联流的元素可能会导致深度调用链,甚至导致StackOverflowException。
TongChen

5

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

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

输出如下:

first
second
third

真好!虽然,另一个图书馆。
GhostCat

-1

最好的方法是使用flatMap,如下所示:

public <T> Stream<T> appendToStream(Stream<T> stream, T element) {
    return stream.flatMap(e -> Stream.of(e, element));
}

该操作在原始流上进行,因此可以只是该流上的另一个中间操作,例如:

    stream.flatMap(e -> Stream.of(e, element))
            .map(...)
            .filter(...)
            .collect(Collectors.toList());

您要添加元素多少次?:D盎司流或原始流中的每个元素一次?
user482745 '19
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.