Nice programing

목록을 합산하는 데 mapToDouble ()이 정말로 필요합니까?

nicepro 2020. 11. 18. 21:26
반응형

목록을 합산하는 데 mapToDouble ()이 정말로 필요합니까? Java 8 스트림으로?


내가 말할 수있는 한, List<Double>Java 8 스트림을 사용하여 합계하는 방법 은 다음과 같습니다.

List<Double> vals = . . . ;
double sum = vals.stream().mapToDouble(Double::doubleValue).sum();

나에게는 mapToDouble(Double::doubleValue)람다와 스트림이 없어야 할 일종의 상용구 "행사"일 뿐이다.

모범 사례에 List따르면 배열보다 인스턴스 를 선호 하지만 이러한 종류의 합계에서는 배열이 더 깔끔해 보입니다.

double[] vals = . . . ;
double sum = Arrays.stream(vals).sum();

물론 다음과 같이 할 수 있습니다.

List<Double> vals = . . . ;
double sum = vals.stream().reduce(0.0, (i,j) -> i+j);

하지만 그 reduce(....)훨씬 이상이다 sum().

나는 이것이 자바의 비 객체 프리미티브를 중심으로 스트림을 개조 해야하는 방식과 관련이 있다는 것을 알지만 여전히 여기에 뭔가 빠졌습니까? 이것을 더 짧게 만들기 위해 오토 박싱을 짜내는 방법이 있습니까? 아니면 이것은 단지 현재의 예술 상태입니까?


업데이트-Answers Digest

다음은 아래의 답변 요약입니다. 여기에 요약이 있지만 독자가 답을 전체적으로 정독 할 것을 촉구합니다.

@dasblinkenlight는 특히 제네릭이 구현 된 방식과 객체가 아닌 프리미티브와의 관계에서 Java 역사에서 더 거슬러 올라간 결정으로 인해 일종의 언 박싱이 항상 필요하다고 설명합니다. 그는 이론적으로 컴파일러가 개봉을 직관하고 간단한 코드를 허용하는 것이 가능하지만 아직 구현되지 않았습니다.

@Holger는 내가 요청한 표현력에 매우 가까운 솔루션을 보여줍니다.

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

나는 새로운 정적 Double.sum()방법을 알지 못했습니다 . 1.8에 추가 된 것은 내가 설명했던 바로 그 목적을위한 것 같습니다. 나는 또한 Double.min()Double.max(). 앞으로는 List<Double>이와 유사한 작업에이 관용구를 확실히 사용할 것 입니다.


제게는 mapToDouble(Double::doubleValue)람다와 스트림이 없어야 하는 것처럼 보입니다.

사용의 필요성 mapToDouble은 유형 삭제를 통해 제네릭을 구현하기로 결정한 결과이며, 본질적으로 제네릭 내부에서 프리미티브를 사용할 가능성에 대한 문을 닫습니다. 필요한 만들려고 같은 결정이다 DoubleStream, IntStreamLongStream스트림 기반의 언 박싱을 제공하는 - 클래스의 가족을.

이것을 더 짧게 만들기 위해 오토 박싱을 짜내는 방법이 있습니까? 아니면 이것은 단지 현재의 예술 상태입니까?

안타깝게도 현재로서는 그렇지 않습니다. 이론적으로 컴파일러가 Stream<Double>이를 DoubleStream암시 적 으로 변환 할 수 있음 을 알아낼 수는 있지만 기본 요소가 unboxed와 같은 방식으로 수행되지 않았습니다.

어레이 기반 솔루션에 관한 한 세 가지 중 가장 효율적입니다. 그러나 다른 두 가지만큼 유연하지 않습니다. 하나 mapToDouble는 사용자 정의 클래스의 속성을 합산 할 수 있고 마지막 하나는 다른 유형의 집계를 수행 할 수 있습니다.

reduce(....) 훨씬 더 길다 sum()

동의합니다.이 접근 방식은 mapToDouble가독성 측면에서 보다 나쁩니다 .


이것을 더 짧게 만들기 위해 오토 박싱을 짜내는 방법이 있습니까?

네, 있습니다. 다음과 같이 간단히 작성할 수 있습니다.

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

이것은 unboxing을 암시 적으로 만들지 만 물론 효율성을 추가하지는 않습니다.

이 때문에 List 되는 박스, 언 박싱은 피할 수 없다. 대안은 다음과 같습니다.

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

그것은하지 mapToDouble않지만 여전히 "… 합계"로 코드를 읽을 수 있습니다.


여기에 다른 방법이 있습니다. Double, Integer또는 목록에 합계, 평균, 최소, 최대 등이 필요한 경우 다음 Long중 하나를 사용할 수 있습니다 Collectors. 예 :

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

18.41 을 인쇄합니다.

메서드 이름은 summingDouble 이고 모든 기본 수학 연산 결과를 포함 하는을 반환하는 summarizingDouble 이라는 또 다른 메서드가 DoubleSummaryStatistics있습니다.

참고 URL : https://stackoverflow.com/questions/24421140/is-maptodouble-really-necessary-for-summing-a-listdouble-with-java-8-streams

반응형