在Java中从java.util.stream.Stream中检索列表
我正在玩Java 8 lambda来轻松过滤集合。 但是,我没有find一个简洁的方法来检索结果作为一个新的列表在同一语句。 这是我迄今为止最简洁的方法:
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);
网上的例子没有回答我的问题,因为他们停止,而不会产生一个新的结果列表。 必须有一个更简洁的方法。 我会期望, Stream
类的方法有toList()
, toSet()
,…
有没有一种方法,variablestargetLongList
可以直接由第三行分配?
你正在做的事情可能是最简单的方法,只要你的stream保持顺序,否则你必须在forEach
之前调用sequential()。
[稍后编辑:对sequential()的调用是必要的原因是,代码(如forEach(targetLongList::add)
)如果stream是并行的将是活泼的。 即使如此,它也不会达到预期的效果,因为每个明确的不确定性 – 即使在顺序stream中,元素处理的顺序也不能保证。 你将不得不使用forEachOrdered
来确保正确的顺序。 Stream APIdevise者的意图是你将在这种情况下使用收集器,如下所示。]
另一种方法是
targetLongList = sourceLongList.stream() .filter(l -> l > 100) .collect(Collectors.toList());
另一种方法是使用Collectors.toCollection
:
targetLongList = sourceLongList.stream(). filter(l -> l > 100). collect(Collectors.toCollection(ArrayList::new));
我喜欢使用util方法返回ArrayList
的收集器,这是我想要的。
我认为使用Collectors.toCollection(ArrayList::new)
的解决scheme对于这样的常见操作来说有点过于嘈杂。
例:
ArrayList<Long> result = sourceLongList.stream() .filter(l -> l > 100) .collect(toArrayList()); public static <T> Collector<T, ?, ArrayList<T>> toArrayList() { return Collectors.toCollection(ArrayList::new); }
有了这个答案,我也想演示如何简单的创build和使用自定义collections家,这是非常有用的一般。
一个更有效的方法(避免创build源列表和filter的自动拆箱):
List<Long> targetLongList = LongStream.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L) .filter(l -> l > 100) .boxed() .collect(Collectors.toList());
如果您有一个基元数组,您可以使用Eclipse集合中可用的基元集合。
LongList sourceLongList = LongLists.mutable.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L); LongList targetLongList = sourceLongList.select(l -> l > 100);
如果你不能从List
更改sourceLongList:
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<>());
如果你想使用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);
注意:我是Eclipse Collections的贡献者。
如果您不介意使用第三方库,AOL的独眼巨人反应 lib(披露我是贡献者)有所有JDK集合types的扩展,包括列表 。 ListX接口扩展java.util.List并添加了大量有用的运算符,包括filter。
你可以简单地写 –
ListX<Long> sourceLongList = ListX.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L); ListX<Long> targetLongList = sourceLongList.filter(l -> l > 100);
ListX也可以从现有的列表(通过ListX.fromIterable)
collect(Collectors.toList());
这是您可以用来将任何stream转换为列表的调用。
如果有人(像我)在寻找方式处理对象而不是原始types,然后使用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);
打印:
List type: class java.util.ArrayList Elem type: class java.lang.Character An alternative way is to insert the following VM o
这里是AbacusUtil的代码
LongStream.of(1, 10, 50, 80, 100, 120, 133, 333).filter(e -> e > 100).toList();
披露:我是AbacusUtil的开发者。
String joined = Stream.of(isRead?"read":"", isFlagged?"flagged":"", isActionRequired?"action":"", isHide?"hide":"") .filter(s -> s != null && !s.isEmpty()) .collect(Collectors.joining(","));
如果你不使用parallel()
这将工作
List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L); List<Long> targetLongList = new ArrayList<Long>(); sourceLongList.stream().peek(i->targetLongList.add(i)).collect(Collectors.toList());