从Java 8中的java.util.stream.Stream中检索List

Dan*_* K. 431 collections lambda java-8 java-stream

我正在玩Java 8 lambdas来轻松过滤集合.但我没有找到一种简洁的方法来将结果作为新列表检索到同一语句中.到目前为止,这是我最简洁的方法:

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);
Run Code Online (Sandbox Code Playgroud)

网上的例子没有回答我的问题,因为他们停止而没有生成新的结果列表.必须有一个更简洁的方式.我本来期望的是,Stream类有方法为toList(),toSet(),...

有没有办法targetLongList可以直接由第三行分配变量?

Mau*_*lin 595

如果您的流保持顺序,您正在做的事情可能是最简单的方式 - 否则您必须先调用sequential()forEach.

[稍后编辑:调用sequential()是必要的原因是,forEach(targetLongList::add)如果流是并行的,代码(如果它)()将会很有效.即便如此,它也不会达到预期的效果,因为forEach明确是不确定的 - 即使在顺序流中,元素处理的顺序也不能得到保证.您必须使用forEachOrdered以确保正确的订购.Stream API设计者的目的是在这种情况下使用收集器,如下所示.

另一种选择是

targetLongList = sourceLongList.stream()
    .filter(l -> l > 100)
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

  • 另外:如果你使用`toList`的静态导入,我认为这些代码会更短,更清晰,更漂亮.这是通过在文件的导入中放置以下内容来完成的:`static import java.util.stream.Collectors.toList;`.然后collect调用只读`.collect(toList())`. (10认同)
  • 在Eclipse中,可以使IDE为方法添加静态导入.这是通过在*Preferences* - >*Java* - >*Editor* - >*Content Assist* - >*Favorites*中添加`Collectors`类来完成的.在此之后,您只需在命中*Ctr + Space*处键入`toLi`以使IDE填写`toList`并添加静态导入. (4认同)
  • 要记住的一件事是`IntStream`和其他一些差不多但不太完整的`theStream'没有`collect(Collector)`方法,你必须调用`IntStream.boxed()`首先将它们转换为常规的"Stream".然后,也许你只想要'toArray()`. (3认同)

Moh*_*lla 174

更新:

另一种方法是使用Collectors.toList:

targetLongList = 
    sourceLongList.stream().
    filter(l -> l > 100).
    collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

以前的方案:

另一种方法是使用Collectors.toCollection:

targetLongList = 
    sourceLongList.stream().
    filter(l -> l > 100).
    collect(Collectors.toCollection(ArrayList::new));
Run Code Online (Sandbox Code Playgroud)

  • 但是,如果您想要特定的List实现,这将非常有用. (58认同)
  • 这个方法的另一个专家,来自`Collectors :: toList` javadoc:"返回的List的类型,可变性,可序列化或线程安全性没有保证;如果需要更多地控制返回的List,请使用` toCollection(供应商)`". (3认同)

Zhe*_*lov 14

Java 16 中有一个新方法Stream.toList(),它将流元素累积到一个不可修改的列表中:

List<Long> targetLongList = sourceLongList
         .stream()
         .filter(l -> l > 100)
         .toList();
Run Code Online (Sandbox Code Playgroud)


Lii*_*Lii 12

我喜欢使用一个util方法,它返回一个收集器,ArrayList当我想要的时候.

我认为使用的解决方案Collectors.toCollection(ArrayList::new)对于这种常见操作来说有点过于嘈杂.

例:

ArrayList<Long> result = sourceLongList.stream()
    .filter(l -> l > 100)
    .collect(toArrayList());

public static <T> Collector<T, ?, ArrayList<T>> toArrayList() {
    return Collectors.toCollection(ArrayList::new);
}
Run Code Online (Sandbox Code Playgroud)

通过这个答案,我还想证明创建和使用自定义收集器是多么简单,这通常非常有用.

  • @LluisMartinez:*“Collectors.toList 可以。”*:不,在很多情况下都不是。因为例如,如果您想稍后在程序中修改列表,则使用 `toList` 不是一个好主意。[`toList` 文档](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toList--) 说:*“没有任何保证返回的 List 的类型、可变性、可序列化性或线程安全性;如果需要对返回的 List 进行更多控制,请使用 `toCollection`。"*。我的回答展示了一种在常见情况下更方便地执行此操作的方法。 (2认同)

Pra*_*mod 6

collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

这是您可以用来将任何流转换为列表的调用。

更具体地说:

    List<String> myList = stream.collect(Collectors.toList()); 
Run Code Online (Sandbox Code Playgroud)

从:

https://www.geeksforgeeks.org/collectors-tolist-method-in-java-with-examples/


Nik*_*kar 5

如果您有一个基元数组,则可以使用Eclipse Collections中提供的基元集合.

LongList sourceLongList = LongLists.mutable.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
LongList targetLongList = sourceLongList.select(l -> l > 100);
Run Code Online (Sandbox Code Playgroud)

如果您无法更改sourceLongList List:

List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);
List<Long> targetLongList = 
    ListAdapter.adapt(sourceLongList).select(l -> l > 100, new ArrayList<>());
Run Code Online (Sandbox Code Playgroud)

如果你想使用LongStream:

long[] sourceLongs = new long[]{1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L};
LongList targetList = 
    LongStream.of(sourceLongs)
    .filter(l -> l > 100)
    .collect(LongArrayList::new, LongArrayList::add, LongArrayList::addAll);
Run Code Online (Sandbox Code Playgroud)

注意:我是Eclipse Collections的贡献者.


msa*_*yag 5

一种更有效的方法(避免创建源列表和过滤器的自动拆箱):

List<Long> targetLongList = LongStream.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L)
    .filter(l -> l > 100)
    .boxed()
    .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)