목록을 합산하는 데 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
, IntStream
및 LongStream
스트림 기반의 언 박싱을 제공하는 - 클래스의 가족을.
이것을 더 짧게 만들기 위해 오토 박싱을 짜내는 방법이 있습니까? 아니면 이것은 단지 현재의 예술 상태입니까?
안타깝게도 현재로서는 그렇지 않습니다. 이론적으로 컴파일러가 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
있습니다.
'Nice programing' 카테고리의 다른 글
반복되는 CSS 애니메이션 지연 (0) | 2020.11.18 |
---|---|
스프레드 시트 데이터를 JSON으로 빠르고 쉽게 변환하려면 어떻게해야합니까? (0) | 2020.11.18 |
Apache Kafka에서 주제를 삭제하는 방법 (0) | 2020.11.18 |
@synthesized 유지 속성에 대한 릴리스는 어떻게 처리됩니까? (0) | 2020.11.18 |
이미지 주위에 텍스트를 배치하는 방법 (0) | 2020.11.18 |