【问题标题】:How to use collect call in Java 8?如何在 Java 8 中使用对方付费电话?
【发布时间】:2015-01-10 09:18:19
【问题描述】:

假设我们有这段无聊的代码,我们都必须使用:

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

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

ArrayList<Long> ids = myList.stream().map(MyObj::getId).collect(Collectors.toList());

但是它给了我这个错误:

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

我尝试强制转换参数,但它给了我未定义的 AR,并且 IDE 没有提供更多建议。

我很好奇在这种情况下您如何使用collect call,但我找不到任何可以正确指导我的信息。有人能解释一下吗?

【问题讨论】:

    标签: java java-8 java-stream collect


    【解决方案1】:

    问题在于Collectors.toList 返回List&lt;T&gt;,这并不奇怪。不是ArrayList

    List<Long> ids = remove.stream()
            .map(MyObj::getId)
            .collect(Collectors.toList());
    

    编程到interface

    来自文档:

    返回一个Collector,它将输入元素累积到一个新的 List不保证类型、可变性、 返回的List 的可序列化性或线程安全性;如果更多 需要控制返回的列表,请使用 toCollection(Supplier).

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

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

    另请注意,习惯上将 import static 与 Java 8 Stream API 一起使用,因此添加:

    import static java.util.stream.Collectors.toCollection;
    

    (我讨厌星号import static,它只会污染命名空间并增加混乱。但选择性import static,尤其是Java 8 实用程序类,可以大大减少冗余代码)

    会导致:

    ArrayList<Long> ids = remove.stream()
            .map(MyObj::getId)
            .collect(toCollection(ArrayList::new));
    

    【讨论】:

    • 实际上结果代码并没有比我们在Java8之前做的更短或更有意义,嗯,性能呢??
    • @Bludream 这不是关于它更短或更有意义,而是关于向 Java 引入一种新范式 - 函数式编程。这允许您以与以前的 Java 迭代非常不同的方式做事。当您需要抽象 行为 而不是 数据 时,函数式编程就会发挥作用。此外,这可能是一个稍长的单行;以前肯定不可能在一行中做到这一点。
    • 我明白了,但就像 OP 一样,我也在寻找一些东西来代替我的代码中到处散布的收集器。
    • @Bludream OP 正在寻求将 collect 操作的结果分配给 ArrayList - 我没有看到任何有关收集器传播的信息。我什至不完全确定这意味着什么......
    • 好吧,问题中的第一行代码,您创建一个空数组并使用循环填充它被称为collector 块。
    【解决方案2】:

    我使用了很多收集器块,在其中创建了一个空数组并使用循环填充它,所以我决定我需要一个自己的实用程序类,而不是再次编写相同的行,这里是:

    public class Collections {
    
        public static <T, O> List<T> collect(Set<O> items, Function<? super O, ? extends T> mapper) {
    
        return items.stream().map(mapper).collect(Collectors.toCollection(ArrayList::new));
    }
    

    }

    并像这样使用它

    List<Product> prods = Collections.collect(basket.getOrderItems(), OrderItem::getProduct);
    

    或者像这样

    List<Long> prods = Collections.collect(basket.getOrderItems(), (item)->item.getProduct().getId());
    

    虽然它看起来更容易阅读,但在这种情况下,流似乎有点慢,look here

    【讨论】:

    • 您可以使用Item::getProduct。学习正确使用方法引用是学习 Java 8 的重要组成部分。添加import static 也消除了直接引用方法的需要。
    • 好的,谢谢!我按照你说的方式工作了,我也讨厌使用import static
    猜你喜欢
    • 2021-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-14
    • 2021-10-29
    • 2014-11-12
    • 1970-01-01
    • 2021-05-24
    相关资源
    最近更新 更多