如何在Java 8中使用collect调用?

Ale*_*rin 23 java collect java-8 java-stream

让我们说我们必须使用这段无聊的代码:

ArrayList<Long> ids = new ArrayList<Long>();
for (MyObj obj : myList){
    ids.add(obj.getId());
}
Run Code Online (Sandbox Code Playgroud)

切换到Java 8后,我的IDE告诉我我可以用这个代码替换collect call它,并自动生成:

ArrayList<Long> ids = myList.stream().map(MyObj::getId).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

但是它给了我这个错误:

Steam中的collect(java.util.stream.Collector)无法应用于:(java.util.stream.Collector,capture,java.util.List>)

我试图铸造参数,但它给我不确定的AR,而IDE没有给任何建议.

我很好奇你collect call在这种情况下如何使用,我找不到任何可以指导我的信息.任何人都可以光明吗?

Bor*_*der 47

问题是Collectors.toList,毫不奇怪,返回a List<T>.不是ArrayList.

List<Long> ids = remove.stream()
        .map(MyObj::getId)
        .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

计划到interface.

从文档:

返回一个Collector将输入元素累积为new的元素 List.还有的类型,可变性,串行化,或的线程安全没有保证List返回 ; 如果需要更多地控制返回的List,请使用 toCollection(Supplier).

强调我的 - 你甚至不能假设List返回的是可变的,更不用说它是一个特定的类.如果你想要一个ArrayList:

ArrayList<Long> ids = remove.stream()
        .map(MyObj::getId)
        .collect(Collectors.toCollection(ArrayList::new));
Run Code Online (Sandbox Code Playgroud)

另请注意,习惯使用import staticJava 8 StreamAPI,因此添加:

import static java.util.stream.Collectors.toCollection;
Run Code Online (Sandbox Code Playgroud)

(我讨厌加星标import static,除了污染名称空间并添加混淆之外什么也没做.但是选择性的import static,尤其是Java 8实用程序类,可以大大减少冗余代码)

会导致:

ArrayList<Long> ids = remove.stream()
        .map(MyObj::getId)
        .collect(toCollection(ArrayList::new));
Run Code Online (Sandbox Code Playgroud)

  • @Bludream不是关于它更短或更有意义,而是关于为Java引入新的范例 - 函数式编程.这允许您以与以前的Java迭代非常不同的方式执行操作.当你需要抽象_behaviour_而不是_data_时,函数式编程就会出现.此外,这可能是一个稍长的单线程; 以前不可能在一行中做到这一点. (4认同)