如何理解此Java 8 Stream collect()方法?


12

我试图将一个int数组转换为List,并且采取了使用Java 8 Stream的陌生路线,并提出了这个建议。

Arrays.stream(arr).boxed().collect(Collectors.toList());

我仍然很难完全理解这条线,

  1. 为什么Collectors.toList()在这种情况下返回一个ArrayList<Integer>实现List接口?为什么不LinkedList<Integer>符合List接口的通用类呢?我找不到这事,除了简短提的ArrayList 这里,在API说明部分。

  2. 左边的 意思是什么?显然是通用返回类型(在我的代码中)。而且我认为是该方法的泛型类型参数,但是如何指定它们呢?我查看了Collector界面文档,但无法吸收它。在此处输入图片说明 Stream.collect()RArrayList<Integer><R, A>


2
1.显然,它确实使用了实际的列表。但是,API公开实际的基础List类型是不明智的。从那时起,他们将永远无法再更改实施。通常,仅公开接口而不公开实际的基础类型通常是一个好主意。2. R是结果类型的通用类型。A收集器的中间累积类型的通用类型。这是收集器工作方式的实现细节。它确实进行了分治(也适用于并行处理),首先将其收集为中间类型。
Zabuzard

10
您几乎从未真正想要LinkedList。乔什·布洛赫(Josh Bloch)发表了一条推文,说“我写了它,但我从不使用它”。
安迪·特纳

4
“为什么Collectors.toList()在这种情况下返回ArrayList<Integer>”“它可能不返回ArrayList。该List实施不确定,所以你不能依靠它返回什么执行。正如javadoc所说:不能保证返回的List 的类型,可变性,可序列化性或线程安全性。”
安德里亚斯(Andreas)

3
并且toList()没有返回ArrayListor List,而是返回a Collector,最终将创建并返回List-,文档也指出:“ ...对返回的List 的类型,可变性,可序列化性或线程安全性不作任何保证;如果需要对返回的列表进行更多控制,请使用toCollection(Supplier) ....“
user85421-Banned,

3
我强烈推荐包装文件
Holger

Answers:


18
  1. 这是默认实现。ArrayList之所以使用,是因为它在大多数情况下都是最好的,但是如果它不适合您,则可以随时定义自己的收集器并为Collection您提供所需的工厂:

    Arrays.stream(arr).boxed().collect(toCollection(LinkedList::new));
  2. 是的,A并且R是此方法的通用参数,R是返回类型,T输入类型和A中间类型,在收集元素的整个过程中都会出现(可能不可见并且与该功能无关)。的javadoc 的开头Collector定义了这些类型(它们在整个doc中是一致的):

    T-归约运算的输入元素的类型
    A- 归约运算的可变累积类型(通常隐藏为实现细节)
    R-归约运算的结果类型


好的我明白了。我想我应该坚持List<Integer> myList = Arrays.stream(arr).boxed().collect(Collectors.toList());并只在myList上调用List接口中声明的方法。否则,如果Oracle决定更改Java8u1024或15中的默认实现,那么我可能会身陷险境?
user3207158

2
@ user3207158该方法返回一个List,因此无论使用哪种实现,其行为都是相同的。在较新版本的Java中不太可能会更改接口。
Andronicus

1
  1. 为什么在这种情况下Collectors.toList()返回实现List接口的ArrayList?

如方法定义所建议的,它将返回一个Collector实现,且Collector供应商为ArrayList。因此,从下面的方法定义中很明显Collectors.toList总是返回ArrayList collector(While it's arguable why toList not toArrayList word is used in method name)。

public static <T>
    Collector<T, ?, List<T>> toList() {
        return new CollectorImpl<>((Supplier<List<T>>) ArrayList::new, List::add,
                                   (left, right) -> { left.addAll(right); return left; },
                                   CH_ID);
    }
  1. 左边的<R, A> R collect(Collector<? super T, A, R> collector)意思是什么

如果您参考文档注释,它将准确地提到这些通用类型是什么:

/*
      @param <R> the type of the result
      @param <A> the intermediate accumulation type of the {@code Collector}
      @param collector the {@code Collector} describing the reduction
      @return the result of the reduction
*/
 <R, A> R collect(Collector<? super T, A, R> collector);

谢谢你,先生。您从哪里获得Collectors.toList()(第一段)的源代码?是openjdk吗?
user3207158

1
没有!我已经在intelli j
Vinay Prajapati
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.