首页 文章

在Java 8中从Double流中收集Long列表

提问于
浏览
18

我有以下代码:

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

此代码不起作用,编译错误是:

接口java.util.stream.LongStream中的方法collect不能应用于给定的类型; required:java.util.function.Supplier <R>,java.util.function.ObjLongConsumer <R>,java.util.function.BiConsumer <R,R> found:java.util.stream.Collector <java.lang . 对象,捕获#1,?,java.util.List <java.lang.Object >> reason:无法推断类型变量R(实际和形式参数列表的长度不同)

我尝试了许多收藏家的用法,但我仍然无法使其发挥作用 . 我究竟做错了什么?

5 回答

  • 25

    如果您使用 map 而不是 mapToLong ,则应该编译 . (我不确定你试图用_1749252做什么是有道理的,但这至少会编译 . )

  • 1

    mapToLong给你LongStreamcollect无法collect .

    这是因为 LongStream

    一系列原始长值元素

    我们不能拥有 List<long> ,我们需要 List<Long> . 因此,为了能够收集它们,我们首先需要将这些原始 long s打包成 Long 对象:

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

    boxed方法为我们提供了 Stream<Long> ,我们可以将其收集到列表中 .

    使用map而不是 mapToLong ,正如Louis Wasserman所建议的那样,也会起作用,因为这将导致 Steam<Long> ,其中值自动加框:

    list.stream().map(i -> i * 2.5)
        .map(Double::doubleToRawLongBits)
        .collect(Collectors.toList());
    
  • 0

    不确定您期望结果如何,但这会产生 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);
    }
    
  • 5

    目前尚不清楚为什么要使用 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());
    

    如果您真的需要IEEE 754表示 double 值,这甚至适用:

    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);
    
  • 13

    这个问题的实质是函数 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类中找到此方法 .

    LongStreamStream 没有延伸关系 .

相关问题