在 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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 10:09:54  来源:igfitidea点击:

Collect list of Long from Double stream in Java 8

javajava-8java-stream

提问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 collectin interface java.util.stream.LongStreamcannot 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

mapToLonggives you a LongStreamwhich is not able to be collect-ed by Collectors.toList.

mapToLong给你一个LongStream不能collectCollectors.toList.

This is because LongStreamis

这是因为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 longs into Longobjects:

我们不能有一个List<long>,我们需要一个List<Long>。因此,为了能够收集它们,我们首先需要将这些原语装箱longLong对象中:

list.stream().map(i -> i * 2.5)
    .mapToLong(Double::doubleToRawLongBits)
    .boxed()                                //< I added this line
    .collect(Collectors.toList());

The boxedmethod gives us a Stream<Long>which we're able to collect to a list.

boxed方法为我们提供了Stream<Long>可以收集到列表中的 a。

Using maprather than mapToLongwill 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 mapinstead of mapToLong. (I'm not sure what you are trying to do with doubleToRawLongBitsmakes 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.5produces doublerather than long, you need a type cast to convert the value, as doubleToRawLongBitsis not the canonical way of converting doubleto 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 mapoperation:

不清楚为什么要使用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 doublevalues:

如果您真的想要 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 StreamAPI):

但请注意,如果您有一个类型与结果类型匹配的临时列表,您可以就地执行操作,而不是创建两个列表(并通过StreamAPI):

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 StreamAPI, you may use the builder rather than an ArrayListfor the source data:

如果您坚持使用StreamAPI,您可以使用构建器而不是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 mapToLongis LongStreaminterface. LongStreamonly has method

这个问题的本质是函数的返回值mapToLongLongStream接口。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 LongStreamand Streamhave no extend relationship.

LongStreamStream没有扩展关系。

回答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());