Java 8流和简单类型

时间:2016-04-21 12:29:57

标签: java java-stream

任何人都可以向我解释为什么以下情况不起作用:

long la[] = new long[] {1,2,3};
Arrays.stream(la).map(Long::valueOf).collect(Collectors.toSet());

当这样做时:

String la[] = new String[] {"1","2","3"};
Arrays.stream(la).map(Long::valueOf).collect(Collectors.toSet());

前者给出了编译错误,而后者没有。编译错误是如此神秘(Eclipse),我无法理解它。

3 个答案:

答案 0 :(得分:2)

Arrays.stream(la)执行生成LongStream的方法public static LongStream stream(long[] array)LongStream map方法返回LongStream(即源long的每个LongStream元素都映射到long元素在目标LongStream)中。 LongStream没有collect方法接受单个参数,这就是collect(Collectors.toSet())没有通过编译的原因。

如果您使用mapToObj

,它应该有效
Set<Long> set = Arrays.stream(la).mapToObj(Long::valueOf).collect(Collectors.toSet());

您的第二个代码段可用,因为此处Arrays.stream会生成Stream引用类型(Stream<String>),其map方法会生成另一个Stream引用类型(在你的情况下Stream<Long>)。在这里,Streamcollect方法接受单个参数 - collect(Collector<? super T, A, R> collector) - 所以collect(Collectors.toSet())可以正常工作。

答案 1 :(得分:2)

代码看起来一样。在这两种情况下,被调用的方法Arrays.stream实际上是不同的:

Stream<String>上,您可以调用map并根据映射器的返回类型返回Stream<R>。但是在LongStream上,map将始终返回LongStream,即原始特化。会发生什么情况Long::valueOf会将您的long元素转换为Long个对象,然后它会自动取消装箱到long;实际上,除了box / unbox之外,该呼叫什么都不做。

然后问题出现在collect电话上。

  • LongStream.collect需要3个参数
  • Stream.collect有一个3参数方法,但也有一个参数方法,这是你用.collect(Collectors.toSet());调用的方法。

因此,您无法在.collect(Collectors.toSet());上致电LongStream。这不会编译:它需要3个参数。

您可以在map上致电mapToObj而不是LongStream:此方法声明返回Stream<R>(而不是LongStream)从mapper的返回类型。在这种情况下,映射器为Long::valueOf,返回Long对象,因此它将返回Stream<Long>

回顾一下:

  long la[] = new long[] {1,2,3};
  Arrays.stream(la).map(Long::valueOf).collect(Collectors.toSet());
//^--LongStream----^^---LongStream----^^     error

  String la[] = new String[] {"1","2","3"};
  Arrays.stream(la).map(Long::valueOf).collect(Collectors.toSet());
//^-Stream<String>-^^--Stream<Long>--^^---- successful call -----^

  long la[] = new long[] {1,2,3};
  Arrays.stream(la).mapToObj(Long::valueOf).collect(Collectors.toSet());
//^--LongStream----^^-----Stream<Long>-----^^---- successful call -----^

答案 2 :(得分:0)

为了回答第一个没有编译的原因,这会创建一个Arrays.stream(la)

long

这会花费每个Long,创建一个long包装器,然后将其解包回LongStream。流仍然是.map(Long::valueOf)

LongStream.collect

这会将单个参数传递给LongStream.collect,但失败是因为.collect(Collectors.toSet()) 需要3个参数:

map

如果您想将mapToObj更改为LongStream(或致电Stream<Long>

,则需要将LongStream.boxed()更改为{{1}}