Is mapToDouble() really necessary for summing a List with Java 8 streams?

后端 未结 3 1165
春和景丽
春和景丽 2020-12-01 05:57

As far as I can tell, the way to sum a List using Java 8 streams is this:

List vals = . . . ;
double sum = vals.stre         


        
相关标签:
3条回答
  • 2020-12-01 06:41

    To me, the mapToDouble(Double::doubleValue) seems [what] lambdas and streams were supposed to dispense with.

    The need to use mapToDouble is a consequence of a decision to implement generics via type erasure, essentially closing the door on any possibility of using primitives inside generics. It is that same decision that made it necessary to create the DoubleStream, IntStream, and LongStream family of classes - to provide a stream-based unboxing.

    Is there some way to squeeze autoboxing in to make this shorter? Or is this just the current state of the art?

    Unfortunately, not at this time: although it is theoretically possible for the compiler to figure out that Stream<Double> can be converted to DoubleStream implicitly, in the same way that the primitives are unboxed, this has not been done.

    As far as your array-based solution goes, it is the most efficient of the three. However, it is not as flexible as the other two: the one with mapToDouble lets you sum any attribute of a custom class, while the last one lets you perform other types of aggregation.

    reduce(....) is so much longer than sum()

    I agree, this approach is worse than mapToDouble in terms of readability.

    0 讨论(0)
  • 2020-12-01 06:50

    Here is another way to do it. If you just need a sum, average, min, max etc. on a list of Double, Integer or Long, you can use one of the available Collectors, e.g.:

    List<Double> doubles = Arrays.asList(3.14, 5.15, 4.12, 6.);
    System.out.println(
            doubles.stream()
                    .collect(Collectors.summingDouble(d -> d))
    );
    

    would print 18.41

    Note, the method name is summingDouble, there is another method called summarizingDouble, which returns DoubleSummaryStatistics, containing all the basic math operations results.

    0 讨论(0)
  • 2020-12-01 06:53

    Is there some way to squeeze autoboxing in to make this shorter?

    Yes, there is. You can simply write:

    double sum = vals.stream().mapToDouble(d->d).sum();
    

    This makes the unboxing implicit but, of course, does not add to efficiency.

    Since the List is boxed, unboxing is unavoidable. An alternative approach would be:

    double sum = vals.stream().reduce(0.0, Double::sum);
    

    It does not do a mapToDouble but still allows reading the code as “… sum”.

    0 讨论(0)
提交回复
热议问题