2016-08-15 56 views
6

(这可能与https://stackoverflow.com/a/30312177/160137有关,但恐怕我还是不明白,所以我这样问我的问题,希望能够得出一个我可以更容易理解的答案。 )为什么Collectors.toList()不在原始集合上工作?

通常,当我有一个流,我可以将其转换为使用在收藏家类的静态方法一个集合:

List<String> strings = Stream.of("this", "is", "a", "list", "of", "strings") 
    .collect(Collectors.toList()); 

类似的过程不会在原始流然而工作,如其他人已经注意到:

IntStream.of(3, 1, 4, 1, 5, 9) 
    .collect(Collectors.toList()); // doesn't compile 

我能做到这一点,而不是:

IntStream.of(3, 1, 4, 1, 5, 9) 
    .boxed() 
    .collect(Collectors.toList()); 

或者我可以这样做:

IntStream.of(3, 1, 4, 1, 5, 9) 
    .collect(ArrayList<Integer>::new, ArrayList::add, ArrayList::addAll); 

的问题是,为什么不Collectors.toList()只是做,对于原始流?是否无法指定包装类型?如果是这样,为什么这不工作:

IntStream.of(3, 1, 4, 1, 5, 9) 
    .collect(Collectors.toCollection(ArrayList<Integer>::new)); // nope 

任何洞察力将不胜感激。

+9

因为(即使在Java-8中),也没有“List ”。原始类型**不是**'对象'。 –

+3

签名中的泛型根本不适用于原始类型。这样简单。 – Dici

+4

明确调用'boxed()'和允许原始流上的盒装收集器之间没有功能差异。如果你问为什么不允许方便,也许设计师想让拳击很容易看出来。 – shmosel

回答

3

那么让IntStream提供一种方法,签名
<R,A> R collect(Collector<? super Integer,A,R> collector)执行隐式装箱。它可以像return boxed().collect(collector);那样简单实施。

问题是“为什么要这样”或者相反:为什么原始流专业化存在?

它们仅仅是出于性能原因而存在,以提供流操作而没有打击开销。所以这是一个明显的设计决定,不包括在通用的Stream接口中已经存在的任何操作,因为所有这些操作都可以简单地调用boxed().genericOperation(…)

answer, you have linked地址相关,但不同的想法。这是关于提供collect方法不接受通用Collector,但一个原始专业化,如Collector.ofInt可以收集int值没有拳击,但对于收集器产生List<Integer>,不可避免地包含盒装值,它没有任何好处。 在预建的收藏家中,只有少数真的可以避免拳击。所有这些都在原始流(count()sum()min()max()summaryStatistics(),...)

它的类/接口数量和潜在的性能增益之间的权衡提供显式终端的操作。在一般情况下,决定创建IntStream,LongStreamDoubleStream,但收集者的情况下,决定不添加这样的专业化。

1

对于原始类型List<>是一个额外的次优用法。因此toArray被认为是足够和充分的(=最佳使用)。

int[] array = IntStream.of(3, 1, 4, 1, 5, 9).toArray(); 
1
IntStream.of(3, 1, 4, 1, 5, 9) 
    .collect(Collectors.toList()); // doesn't compile 

流是int,通用方法toList()假定的对象。没有匹配。

IntStream.of(3, 1, 4, 1, 5, 9) 
    .boxed() 
    .collect(Collectors.toList()); 

流是Integer,通用方法toList()假定的对象。比赛!

IntStream.of(3, 1, 4, 1, 5, 9) 
    .collect(ArrayList<Integer>::new, ArrayList::add, ArrayList::addAll); 

流是int,和它的等toList()固定通用方法Integer。除IntStream没有接受收集器的方法collect()外,只有3参数方法。

相关问题