简体   繁体   English

Java 8流和简单类型

[英]Java 8 streams and simple types

Can anyone explain to me why the following does not work: 任何人都可以向我解释为什么以下不起作用:

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

When this does: 这样做:

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

The former gives a compilation error while the latter does not. 前者给出了编译错误,而后者没有。 The compilation error is so cryptic (Eclipse) that I cannot make sense of it. 编译错误是如此神秘(Eclipse),我无法理解它。

Arrays.stream(la) executes the method public static LongStream stream(long[] array) which produces a LongStream . Arrays.stream(la)执行方法public static LongStream stream(long[] array) ,其产生一个LongStream LongStream 's map method returns a LongStream (ie each long element of the source LongStream is mapped to a long element in the target LongStream ). LongStreammap方法返回一个LongStream (即源LongStream每个long元素都映射到目标LongStreamlong元素)。 LongStream doesn't have a collect method that accepts a single argument, which is why collect(Collectors.toSet()) doesn't pass compilation. LongStream没有接受单个参数的collect方法,这就是collect(Collectors.toSet())不通过编译的原因。

It should work if you use mapToObj : 如果你使用mapToObj它应该工作:

Set<Long> set = Arrays.stream(la).mapToObj(Long::valueOf).collect(Collectors.toSet());

Your second snippet works since here Arrays.stream produces a Stream of a reference type ( Stream<String> ) whose map method produces another Stream of a reference type ( Stream<Long> in your case). 你的第二个片段工作,因为这里Arrays.stream产生Stream的引用类型( Stream<String> ),其map方法产生另一个Stream的引用类型( Stream<Long>你的情况)。 Here, Stream has a collect method that accepts a single argument - collect(Collector<? super T, A, R> collector) - so collect(Collectors.toSet()) works. 这里, Stream有一个collect方法接受一个参数 - collect(Collector<? super T, A, R> collector) - 所以collect(Collectors.toSet())可以工作。

The code only looks the same. 代码看起来一样。 The method Arrays.stream that is being called is actually different in both cases: 在这两种情况下,被调用的方法Arrays.stream实际上是不同的:

On a Stream<String> , you can call map and return a Stream<R> based on the return type of the mapper. Stream<String> ,您可以调用map并根据mapper的返回类型返回Stream<R> But on a LongStream , map will always return a LongStream , that is the primitive specialization. 但是在LongStreammap将始终返回LongStream ,即原始特化。 What happens is that Long::valueOf will turn your long element into a Long object and then it will be automatically unboxed into a long ; 会发生什么是Long::valueOf会将你的long元素变成一个Long对象,然后它会自动解包成long ; effectively, the call is doing nothing except a box / unbox. 实际上,除了box / unbox之外,该呼叫什么都不做。

Then the problem appears on the collect call. 然后问题出现在collect呼叫上。

  • LongStream.collect expects 3 arguments LongStream.collect需要3个参数
  • Stream.collect has a 3 argument method but also a 1 argument method, which is the one you call with .collect(Collectors.toSet()); Stream.collect有一个3参数方法,但也有一个参数方法,它是你用.collect(Collectors.toSet());调用的方法.collect(Collectors.toSet()); .

So you can't call .collect(Collectors.toSet()); 所以你不能调用.collect(Collectors.toSet()); on a LongStream . LongStream This won't compile: it expects 3 arguments. 这不会编译:它需要3个参数。

What you can do is call mapToObj instead of map on the LongStream : this method declares to return a Stream<R> (instead of a LongStream ) from the return type of the mapper. 你可以做的是在LongStream上调用mapToObj而不是map :这个方法声明从mapper的返回类型返回Stream<R> (而不是LongStream )。 In this case, the mapper is Long::valueOf that returns a Long object so it will return a Stream<Long> . 在这种情况下,映射器是Long::valueOf ,它返回一个Long对象,因此它将返回Stream<Long>

To recap: 回顾一下:

  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 -----^

To answer why the first one doesn't compile, this creates a LongStream : 为了回答第一个没有编译的原因,这会创建一个LongStream

Arrays.stream(la)

This takes each long , creates a Long wrapper, then unboxes it back to long . 这需要每个long ,创建一个Long包装器,然后将它重新打包回long Stream is still a LongStream : Stream仍然是一个LongStream

.map(Long::valueOf)

This passes a single parameter to LongStream.collect , which fails because LongStream.collect required 3 parameters: 这会将单个参数传递给LongStream.collect ,但由于LongStream.collect需要3个参数,因此会失败:

.collect(Collectors.toSet())

You need to change the map to mapToObj if you want to change the LongStream into a Stream<Long> (or call LongStream.boxed() ) 您需要更改mapmapToObj如果你想改变LongStreamStream<Long> (或致电LongStream.boxed()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM