在 Java 8 中从双流中收集 Long 的列表
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/30785278/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Collect list of Long from Double stream in Java 8
提问by aldrael
I have the following code:
我有以下代码:
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());
This code doesn't work and the compilation error is:
此代码不起作用,编译错误是:
method
collect
in interfacejava.util.stream.LongStream
cannot be applied to given types;
required:java.util.function.Supplier<R>,java.util.function.ObjLongConsumer<R>,java.util.function.BiConsumer<R,R>
found:java.util.stream.Collector<java.lang.Object,capture#1 of ?,java.util.List<java.lang.Object>>
reason: cannot infer type-variable(s)R
(actual and formal argument lists differ in length)
方法
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
(实际和形式参数列表的长度不同)
I have tried many usages of Collectors but I still can't make it to work. What am I doing wrong?
我已经尝试了很多收集器的用法,但我仍然无法让它工作。我究竟做错了什么?
采纳答案by Michael
mapToLong
gives you a LongStream
which is not able to be collect
-ed by Collectors.toList
.
mapToLong
给你一个LongStream
不能collect
被Collectors.toList
.
This is because LongStream
is
这是因为LongStream
是
A sequence of primitivelong-valued elements
原始长值元素序列
We can't have a List<long>
, we need a List<Long>
. Therefore to be able to collect them we first need to box these primitive long
s into Long
objects:
我们不能有一个List<long>
,我们需要一个List<Long>
。因此,为了能够收集它们,我们首先需要将这些原语装箱long
到Long
对象中:
list.stream().map(i -> i * 2.5)
.mapToLong(Double::doubleToRawLongBits)
.boxed() //< I added this line
.collect(Collectors.toList());
The boxed
method gives us a Stream<Long>
which we're able to collect to a list.
该boxed
方法为我们提供了Stream<Long>
可以收集到列表中的 a。
Using map
rather than mapToLong
will also work because that will result in a Steam<Long>
where the values are automatically boxed:
使用map
而不是mapToLong
也将起作用,因为这将导致Steam<Long>
值自动装箱:
list.stream().map(i -> i * 2.5)
.map(Double::doubleToRawLongBits)
.collect(Collectors.toList());
回答by Louis Wasserman
This should compile if you use map
instead of mapToLong
. (I'm not sure what you are trying to do with doubleToRawLongBits
makes any sense, but that will at least compile.)
如果您使用map
而不是mapToLong
. (我不确定您要做doubleToRawLongBits
什么有意义,但这至少可以编译。)
回答by OldCurmudgeon
Not sure what you expect your results to look like but this generates a List<Long>
.
不确定您期望的结果是什么样的,但这会生成一个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);
}
回答by Holger
It's not clear why you want to use doubleToRawLongBits
. If your problem is that the multiplication with 2.5
produces double
rather than long
, you need a type cast to convert the value, as doubleToRawLongBits
is not the canonical way of converting double
to long
. Instead, this method returns the IEEE 754 representation of the value which is only interesting in very special cases. Note that you can perform the conversion right inside the first map
operation:
不清楚为什么要使用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());
This even applies if you really want the IEEE 754 representation of double
values:
如果您真的想要 IEEE 754double
值的表示,这甚至适用:
List<Long> newList = list.stream().map(i -> Double.doubleToRawLongBits(i * 2.5))
.collect(Collectors.toList());
But note that if you have a temporary list whose type matching the result type, you may perform the operation in-place instead of creating two lists (and going through the Stream
API):
但请注意,如果您有一个类型与结果类型匹配的临时列表,您可以就地执行操作,而不是创建两个列表(并通过Stream
API):
List<Long> list = new ArrayList<>();
list.add(4L);
list.add(92L);
list.add(100L);
list.replaceAll(i -> (long)(i * 2.5));
again, the same applies even ifyou want IEEE 754 bits:
再次,这同样适用,甚至如果你想IEEE 754位:
List<Long> list = new ArrayList<>();
list.add(4L);
list.add(92L);
list.add(100L);
list.replaceAll(i -> Double.doubleToRawLongBits(i * 2.5));
If you insist on using the Stream
API, you may use the builder rather than an ArrayList
for the source data:
如果您坚持使用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);
回答by Monet
The essence of this problem is that the return value of function mapToLong
is LongStream
interface. LongStream
only has method
这个问题的本质是函数的返回值mapToLong
是LongStream
接口。LongStream
只有方法
<R> R collect(Supplier<R> supplier,
ObjLongConsumer<R> accumulator,
BiConsumer<R, R> combiner);
You may be want to use method
您可能想要使用方法
<R, A> R collect(Collector<? super T, A, R> collector);
You can find this method in java.util.stream.Streamclass.
您可以在java.util.stream.Stream类中找到此方法。
the LongStream
and Stream
have no extend relationship.
在LongStream
和Stream
没有扩展关系。
回答by JavaMan
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());