Retrieving a List from a java.util.stream.Stream in Java 8
我正在玩Java 8 lambdas来轻松过滤集合。 但我没有找到一种简洁的方法来将结果作为新列表检索到同一语句中。 到目前为止,这是我最简洁的方法:
1 2 3 | 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); |
网上的例子没有回答我的问题,因为他们停止而没有生成新的结果列表。 必须有一个更简洁的方式。 我原以为,
有没有办法可以直接由第三行分配变量
你正在做的事情可能是最简单的方法,只要你的流保持顺序&mdash;否则你将不得不在
[稍后编辑:调用sequential()是必要的原因是,如果流是并行的,代码(
另一种选择是
1 2 3 | targetLongList = sourceLongList.stream() .filter(l -> l > 100) .collect(Collectors.toList()); |
更新:
另一种方法是使用
1 2 3 4 | targetLongList = sourceLongList.stream(). filter(l -> l > 100). collect(Collectors.toList()); |
以前的方案:
另一种方法是使用
1 2 3 4 | targetLongList = sourceLongList.stream(). filter(l -> l > 100). collect(Collectors.toCollection(ArrayList::new)); |
我喜欢使用一个util方法,当我想要的时候返回
我认为使用
例:
1 2 3 4 5 6 7 | ArrayList<Long> result = sourceLongList.stream() .filter(l -> l > 100) .collect(toArrayList()); public static < T > Collector<T, ?, ArrayList< T >> toArrayList() { return Collectors.toCollection(ArrayList::new); } |
通过这个答案,我还想证明创建和使用自定义收集器是多么简单,这通常非常有用。
如果您有一个基元数组,则可以使用Eclipse Collections中提供的基元集合。
1 2 | LongList sourceLongList = LongLists.mutable.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L); LongList targetLongList = sourceLongList.select(l -> l > 100); |
如果您无法从
1 2 3 | 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<>()); |
如果要使用
1 2 3 4 5 | 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的贡献者。
更有效的方法(避免创建源列表和过滤器自动取消装箱):
1 2 3 4 | List<Long> targetLongList = LongStream.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L) .filter(l -> l > 100) .boxed() .collect(Collectors.toList()); |
1 | collect(Collectors.toList()); |
这是您可以用来将任何Stream转换为List的调用。
LongStream类提供了另一种collect方法变体
类似地,IntStream和DoubleStream类也是如此。
1 2 3 | <R> R collect(Supplier<R> supplier, ObjLongConsumer<R> accumulator, BiConsumer<R,R> combiner) |
对此流的元素执行可变减少操作。可变减少是其中减少的值是可变结果容器(例如ArrayList),并且通过更新结果的状态而不是通过替换结果来合并元素。这产生的结果相当于:
1 2 3 4 | R result = supplier.get(); for (long element : this stream) accumulator.accept(result, element); return result; |
与reduce(long,LongBinaryOperator)一样,可以并行化收集操作,而无需额外的同步。
这是终端操作。
使用此收集方法回答您的问题如下:
1 2 3 | LongStream.of(1L, 2L, 3L, 3L).filter(i -> i > 2) .collect(ArrayList::new, (list, value) -> list.add(value) , (list1, list2) -> list1.addAll(list2)); |
下面是方法参考变体,它非常聪明,但有些难以理解:
1 2 | LongStream.of(1L, 2L, 3L, 3L).filter(i -> i > 2) .collect(ArrayList::new, List::add , List::addAll); |
下面是HashSet变体:
1 2 | LongStream.of(1L, 2L, 3L, 3).filter(i -> i > 2) .collect(HashSet::new, HashSet::add, HashSet::addAll); |
类似LinkedList变体是这样的:
1 2 3 | LongStream.of(1L, 2L, 3L, 3L) .filter(i -> i > 2) .collect(LinkedList::new, LinkedList::add, LinkedList::addAll); |
如果您不介意使用第三方库,AOL的cyclops-react lib(披露我是贡献者)具有所有JDK Collection类型的扩展,包括List。 ListX接口扩展了java.util.List并添加了大量有用的运算符,包括filter。
你可以简单地写 -
1 2 | ListX<Long> sourceLongList = ListX.of(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L); ListX<Long> targetLongList = sourceLongList.filter(l -> l > 100); |
ListX也可以从现有List创建(通过ListX.fromIterable)
您可以重写代码如下:
1 2 | List<Long> sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L); List<Long> targetLongList = sourceLongList.stream().filter(l -> l > 100).collect(Collectors.toList()); |
1 2 3 4 | String joined = Stream.of(isRead?"read":"", isFlagged?"flagged":"", isActionRequired?"action":"", isHide?"hide":"") .filter(s -> s != null && !s.isEmpty()) .collect(Collectors.joining(",")); |
这是AbacusUtil的代码
1 | LongStream.of(1, 10, 50, 80, 100, 120, 133, 333).filter(e -> e > 100).toList(); |
披露:我是AbacusUtil的开发人员。
如果有人(像我一样)在寻找处理Objects而不是原始类型的方法,那么使用
1 2 3 4 5 6 7 8 9 10 11 12 | 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); |
打印:
1 2 3 | List type: class java.util.ArrayList Elem type: class java.lang.Character An alternative way is to insert the following VM o |
如果你不使用
1 2 3 4 5 | 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()); |