我有以下代码:
List<Long> list = new ArrayList<>();
list.add(4L);
list.add(92L);
list.add(100L);
List<Long> newList = list.stream().map(i -> i * 2.5)
.mapToLong(Double::doubleToRawLongBits)
.collect(Collectors.toList());
此代码不起作用,编译错误为:
接口collect
中的方法
java.util.stream.LongStream
无法应用于给定类型;
必填:java.util.function.Supplier<R>,java.util.function.ObjLongConsumer<R>,java.util.function.BiConsumer<R,R>
发现:java.util.stream.Collector<java.lang.Object,capture#1 of ?,java.util.List<java.lang.Object>>
原因:无法推断类型变量R
(实际和正式的参数列表长度不同)
我尝试了许多收藏家的用法,但我仍然无法使其发挥作用。 我做错了什么?
答案 0 :(得分:34)
mapToLong
为您提供了一个LongStream
,collect
无法Collectors.toList
编辑。
这是因为LongStream
是
一系列原始长值元素
我们不能拥有List<long>
,我们需要List<Long>
。因此,为了能够收集它们,我们首先需要将这些原始long
封装到Long
个对象中:
list.stream().map(i -> i * 2.5)
.mapToLong(Double::doubleToRawLongBits)
.boxed() //< I added this line
.collect(Collectors.toList());
boxed
方法为我们提供了Stream<Long>
,我们可以将其收集到列表中。
根据map
的建议,使用Louis Wasserman而不是mapToLong
也会有效,因为这样会产生Steam<Long>
,其中的值会自动加框:
list.stream().map(i -> i * 2.5)
.map(Double::doubleToRawLongBits)
.collect(Collectors.toList());
答案 1 :(得分:15)
如果您使用map
而不是mapToLong
,则应编译。 (我不确定你试图用doubleToRawLongBits
做什么是有道理的,但这至少会编译。)
答案 2 :(得分:5)
不确定您希望结果如何,但这会产生List<Long>
。
public void test() {
List<Long> list = new ArrayList<>();
list.add(4L);
list.add(92L);
list.add(100L);
List<Long> newList = list.stream()
// Times 1.5.
.map(i -> i * 2.5)
// Grab the long bits.
.mapToLong(Double::doubleToRawLongBits)
// Box them.
.boxed()
// Make a list.
.collect(Collectors.toList());
System.out.println(newList);
}
答案 3 :(得分:1)
目前尚不清楚为什么要使用doubleToRawLongBits
。如果问题是与2.5
的乘法产生double
而不是long
,则需要使用类型转换来转换值,因为doubleToRawLongBits
不是规范的转换方式double
到long
。相反,此方法返回值的IEEE 754表示,这在非常特殊的情况下才有意义。请注意,您可以在第一个map
操作中执行转换:
List<Long> list = new ArrayList<>();
list.add(4L);
list.add(92L);
list.add(100L);
List<Long> newList = list.stream().map(i -> (long)(i * 2.5))
.collect(Collectors.toList());
如果您真的想要double
值的IEEE 754表示,这甚至适用:
List<Long> newList = list.stream().map(i -> Double.doubleToRawLongBits(i * 2.5))
.collect(Collectors.toList());
但请注意,如果您有一个类型与结果类型匹配的临时列表,您可以就地执行操作,而不是创建两个列表(并通过Stream
API):
List<Long> list = new ArrayList<>();
list.add(4L);
list.add(92L);
list.add(100L);
list.replaceAll(i -> (long)(i * 2.5));
再次,即使如果你想要IEEE 754位,也是如此:
List<Long> list = new ArrayList<>();
list.add(4L);
list.add(92L);
list.add(100L);
list.replaceAll(i -> Double.doubleToRawLongBits(i * 2.5));
如果您坚持使用Stream
API,则可以使用构建器而不是ArrayList
作为源数据:
Stream.Builder<Long> b = Stream.builder();
b.add(4L);
b.add(92L);
b.add(100L);
List<Long> newList = b.build().map(i -> (long)(i * 2.5))
.collect(Collectors.toList());
newList.forEach(System.out::println);
答案 4 :(得分:1)
这个问题的实质是函数mapToLong
的返回值是LongStream
接口。 LongStream
只有方法
<R> R collect(Supplier<R> supplier,
ObjLongConsumer<R> accumulator,
BiConsumer<R, R> combiner);
您可能想要使用方法
<R, A> R collect(Collector<? super T, A, R> collector);
您可以在java.util.stream.Stream课程中找到此方法。
LongStream
和Stream
没有延伸关系。
答案 5 :(得分:0)
HashMap<String, Map<String, Long>> map = new HashMap<>();
List<Entry<String, Map<String, Long>>> sortedList = map
.entrySet()
.stream()
.sorted((a, b) -> Long.compare(
a.getValue().values().stream().mapToLong(l -> l).sum(),
b.getValue().values().stream().mapToLong(l -> l).sum()))
.collect(Collectors.toList());