[英]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
). LongStream
的map
方法返回一个LongStream
(即源LongStream
每个long
元素都映射到目标LongStream
的long
元素)。 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
实际上是不同的:
stream(long[])
which returns a LongStream
. stream(long[])
,它返回一个LongStream
。 This is a primitive specialization of a stream for long
elements. long
元素流的原始特化。 stream(T[])
(where T = String
here) wich returns a Stream<String>
stream(T[])
(其中T = String
)返回Stream<String>
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. 但是在
LongStream
, map
将始终返回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()
) 您需要更改
map
以mapToObj
如果你想改变LongStream
成Stream<Long>
(或致电LongStream.boxed()
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.