本文翻译自:Retrieving a List from a java.util.stream.Stream in Java 8
I was playing around with Java 8 lambdas to easily filter collections. 我在玩Java 8 lambda来轻松过滤集合。 But I did not find a concise way to retrieve the result as a new list within the same statement. 但是我没有找到一种简洁的方法来在同一条语句中以新列表的形式检索结果。 Here is my most concise approach so far: 到目前为止,这是我迄今为止最简洁的方法:
List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
List<Long> targetLongList = new ArrayList<>();
sourceLongList.stream().filter(l -> l > 100).forEach(targetLongList::add);
Examples on the net did not answer my question because they stop without generating a new result list. 网上的示例没有回答我的问题,因为它们停止了而没有生成新的结果列表。 There must be a more concise way. 必须有一种更简洁的方法。 I would have expected, that the Stream
class has methods as toList()
, toSet()
, … 我本来希望Stream
类具有toList()
, toSet()
,...等方法。
Is there a way that the variables targetLongList
can be directly be assigned by the third line? 有没有一种方法可以由第三行直接分配变量targetLongList
?
#1楼
参考:https://stackoom.com/question/10E2b/从Java-中的java-util-stream-Stream检索列表
#2楼
What you are doing may be the simplest way, provided your stream stays sequential—otherwise you will have to put a call to sequential() before forEach
. 如果您的流保持顺序运行,那么您正在做的事情可能是最简单的方法,否则您将必须在forEach
之前调用对sequence()的调用。
[later edit: the reason the call to sequential() is necessary is that the code as it stands ( forEach(targetLongList::add)
) would be racy if the stream was parallel. [稍后编辑:必须调用forEach(targetLongList::add)
()的原因是,如果流是并行的,那么按forEach(targetLongList::add)
编写的代码( forEach(targetLongList::add)
)会很forEach(targetLongList::add)
。 Even then, it will not achieve the effect intended, as forEach
is explicitly nondeterministic—even in a sequential stream the order of element processing is not guaranteed. 即使这样,它也不会达到预期的效果,因为forEach
显然是不确定的-即使在顺序流中,也不能保证元素处理的顺序。 You would have to use forEachOrdered
to ensure correct ordering. 您将必须使用forEachOrdered
来确保正确的排序。 The intention of the Stream API designers is that you will use collector in this situation, as below.] Stream API设计人员的目的是在这种情况下使用收集器,如下所示。]
An alternative is 替代方法是
targetLongList = sourceLongList.stream()
.filter(l -> l > 100)
.collect(Collectors.toList());
#3楼
Updated: 更新:
Another approach is to use Collectors.toList
: 另一种方法是使用Collectors.toList
:
targetLongList =
sourceLongList.stream().
filter(l -> l > 100).
collect(Collectors.toList());
Previous Solution: 先前的解决方案:
Another approach is to use Collectors.toCollection
: 另一种方法是使用Collectors.toCollection
:
targetLongList =
sourceLongList.stream().
filter(l -> l > 100).
collect(Collectors.toCollection(ArrayList::new));
#4楼
In case someone (like me) out there is looking for ways deal with Objects instead of primitive types then use mapToObj()
如果有人(像我一样)正在寻找处理对象而不是原始类型的方法,然后使用mapToObj()
String ss = "An alternative way is to insert the following VM option before "
+ "the -vmargs option in the Eclipse shortcut properties(edit the "
+ "field Target inside the Shortcut tab):";
List<Character> ll = ss
.chars()
.mapToObj(c -> new Character((char) c))
.collect(Collectors.toList());
System.out.println("List type: " + ll.getClass());
System.out.println("Elem type: " + ll.get(0).getClass());
ll.stream().limit(50).forEach(System.out::print);
prints: 印刷品:
List type: class java.util.ArrayList
Elem type: class java.lang.Character
An alternative way is to insert the following VM o
#5楼
I like to use a util method that returns a collector for ArrayList
when that is what I want. 我喜欢使用util方法,这是我想要的时候返回ArrayList
的收集器。
I think the solution using Collectors.toCollection(ArrayList::new)
is a little too noisy for such a common operation. 我认为使用Collectors.toCollection(ArrayList::new)
的解决方案对于这种常见操作而言有点过于嘈杂。
Example: 例:
ArrayList<Long> result = sourceLongList.stream()
.filter(l -> l > 100)
.collect(toArrayList());
public static <T> Collector<T, ?, ArrayList<T>> toArrayList() {
return Collectors.toCollection(ArrayList::new);
}
With this answer I also want to demonstrate how simple it is to create and use custom collectors, which is very useful generally. 通过这个答案,我还想证明创建和使用自定义收集器有多么简单,这通常非常有用。
#6楼
If you don't mind using 3rd party libraries, AOL's cyclops-react lib (disclosure I am a contributor) has extensions for all JDK Collection types, including List . 如果您不介意使用第3方库,那么AOL的cyclops-react lib(披露我是一名贡献者)具有所有JDK Collection类型的扩展,包括List 。 The ListX interface extends java.util.List and adds a large number of useful operators, including filter. ListX接口扩展了java.util.List并添加了大量有用的运算符,包括过滤器。
You can simply write- 您可以简单地写-
ListX<Long> sourceLongList = ListX.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
ListX<Long> targetLongList = sourceLongList.filter(l -> l > 100);
ListX also can be created from an existing List (via ListX.fromIterable) ListX也可以从现有列表创建(通过ListX.fromIterable)