我在玩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);
网上的例子没有回答我的问题,因为它们没有生成一个新的结果列表就停止了。一定有更简洁的方法。我希望 "流 "类有 "toList()"、"toSet() "等方法。
有没有办法让变量 "targetLongList "可以直接被第三行分配?
你所做的可能是最简单的方法,只要你的流保持顺序—否则你将不得不在forEach
前调用sequential()。
[稍后编辑:对sequential()的调用是必要的,因为目前的代码(forEach(targetLongList::add)
)如果流是并行的,就会很有创意。即使如此,也不能达到预期的效果,因为forEach
是明确的非确定性的—即使在一个顺序流中,元素处理的顺序也不能保证。你必须使用forEachOrdered
来确保正确的顺序。Stream API设计者的意图是,在这种情况下,你会使用收集器,如下所示]。
另一个选择是
targetLongList = sourceLongList.stream()
.filter(l -> l > 100)
.collect(Collectors.toList());
已更新。
另一种方法是使用Collectors.toList
。
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)
的解决方案对于这样一个常见的操作来说,有点过于嘈杂。
例如:{{{16965549}}。
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] 中提供的基元集合。
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的撰稿人。 我是Eclipse Collections的撰稿人。
如果你不介意使用第三方库,AOL'的[cyclops-react][1] lib (披露我是贡献者)对所有[JDK Collection][2] 类型都有扩展,包括[List][3] 。 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也可以从现有的List中创建(通过ListX.fromIterable)。
[1]: https://github.com/aol/cyclops-react [2]: _COPY11@johnmcclean/extending-jdk-8-collections-8ae8d43dd75e#.j5lxtrqze [3]: http://static.javadoc.io/com.aol.simplereact/cyclops-react/1.0.0-RC1/com/aol/cyclops/data/collections/extensions/standard/ListX.html
LongStream类提供了另一种变体的收集方法,即 类似的还有IntStream和DoubleStream类。
<R> R collect(Supplier<R> supplier,
ObjLongConsumer<R> accumulator,
BiConsumer<R,R> combiner)
在此流的元素上执行一个可突变的还原操作。 可突变还原是指还原值是一个可突变的结果容器,如ArrayList,元素通过更新结果的状态而不是替换结果来合并。 这样产生的结果相当于
R result = supplier.get();
for (long element : this stream)
accumulator.accept(result, element);
return result;
**与 reduce(long, LongBinaryOperator) 一样,收集操作可以并行化,而不需要额外的同步。 这是一个终端操作。
对于你的问题,这个collect方法的答案如下。
LongStream.of(1L, 2L, 3L, 3L).filter(i -> i > 2)
.collect(ArrayList::new, (list, value) -> list.add(value)
, (list1, list2) -> list1.addAll(list2));
下面是方法参考的变体,它是相当聪明的,但有些什么棘手的理解。
LongStream.of(1L, 2L, 3L, 3L).filter(i -> i > 2)
.collect(ArrayList::new, List::add , List::addAll);
下面将是HashSet的变体。
LongStream.of(1L, 2L, 3L, 3).filter(i -> i > 2)
.collect(HashSet::new, HashSet::add, HashSet::addAll);
类似的LinkedList变体是这样的。
LongStream.of(1L, 2L, 3L, 3L)
.filter(i -> i > 2)
.collect(LinkedList::new, LinkedList::add, LinkedList::addAll);
你可以改写如下代码。
List<Long>.LongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L);;。
sourceLongList = Arrays.asList(1L, 10L, 50L, 80L, 100L, 120L, 133L, 333L)。
List<Long>。
targetLongList = sourceLongList.stream().filter(l ->
l >
100).collect(Collectors.toList());
如果有人(像我一样)正在寻找处理对象而不是原始类型的方法,那么可以使用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][1]的代码。
LongStream.of(1, 10, 50, 80, 100, 120, 133, 333).filter(e -> e > 100).toList();
披露:我'是AbacusUtil的开发者。
如果你不使用 "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());