2017-02-13 27 views
10

Tôi có một phương thức tạo danh sách và tôi muốn nó trả lại giá trị trung bình của danh sách dưới dạng Giá trị tùy chọn.Chuyển đổi OptionalDouble thành Tùy chọn <java.lang.Double>

Tuy nhiên, khi tôi tính giá trị trung bình bằng cách sử dụng Java 8, tôi luôn nhận được giá trị trả về dưới dạng OptionalDouble.

Làm thế nào để chuyển đổi

OptionalDouble to Optional<Double>? 

Dưới đây là mã của tôi để tính trung bình:

private static Optional<Double> averageListValue() { 
    // Build list 
    List<Double> testList = new ArrayList<>(); 
    testList.add(...); 
    ... 
    ... 


    return testList.stream().mapToDouble(value -> value).average(); 
} 

Cảm ơn.

+2

Làm thế nào về 'getAsDouble' trên OptionalDouble mà sẽ giúp bạn có được trung bình trong' double' đó là những gì bạn cuối cùng sẽ muốn. – VHS

+3

Một OptionalDouble là hiệu quả hơn; gần hơn với 'double', do đó việc chuyển đổi mã sử dụng từ' Tùy chọn 'thành' OptionalDouble' sẽ có vẻ tốt hơn. Nhưng sau đó, tôi nghĩ rằng bạn biết điều đó và có lý do của bạn. –

+2

Nếu mã tạo danh sách như được hiển thị, bạn đã biết rằng nó sẽ không bao giờ trống. Vậy tại sao lại trả về một 'Tùy chọn'? – Holger

Trả lời

1

Tôi không biết nếu có tồn tại một giải pháp gọn gàng, nhưng ths nên làm việc:

OptionalDouble optionalDouble = testList.stream().mapToDouble(value -> value).average(); 
return Optional.ofNullable(optionalDouble.isPresent() ? optionalDouble.getAsDouble() : null); 
1

Chỉ cần cho vui, tôi muốn để xem nếu nó có thể được viết trong một tuyên bố duy nhất, mà không cần phải biến tùy chọn tempouble. Dưới đây là tốt nhất mà tôi đã đưa ra:

return testList.stream().collect(Collectors.collectingAndThen(
    Collectors.summarizingDouble(Double::doubleValue), 
    stat -> Optional.ofNullable(stat.getCount()>0 ? stat.getAverage() : null))); 
1

tôi đến đây "một dòng" (câu lệnh) giải pháp:

return ((Function<OptionalDouble, Optional<Double>>) od 
      -> od.isPresent() ? Optional.of(od.getAsDouble()) : Optional.empty()) 
      .apply(testList.stream().mapToDouble(v -> v).average()); 

BTW, chỉ vì lợi ích của minimalism, nếu bạn sẽ thực hiện nhập tĩnh:

import static java.util.Optional.*; 

bạn có thể bỏ qua Optional., điều làm cho nó ít lộn xộn hơn một chút.

6

tôi muốn đi cho cách tiếp cận này:

private static Optional<Double> convert(OptionalDouble od) 
{ 
    return od.isPresent() ? 
     Optional.of(od.getAsDouble()) : Optional.empty(); 
} 
4

BTW, tôi thấy một giải pháp, trong đó có hình thức đơn giản nhất.

Tôi đã bắt đầu suy nghĩ về: khi kết quả trung bình có thể trống? Chỉ khi danh sách nó tự rỗng, phải không? Vì vậy, nếu chúng tôi chắc chắn danh sách đó không phải là trống rỗng, hơn chúng ta có thể yên tâm làm getAsDouble():

return Optional.ofNullable(testList.isEmpty() ? null : 
     testList.stream().mapToDouble(v -> v).average().getAsDouble()) 

(từ quan điểm thực hiện quan điểm này có thể hiệu quả hơn so với việc tạo giấy gói lambda bổ sung, như đã được đề xuất trong câu trả lời tương tự.)

+3

Đây là một thử nghiệm kép, đầu tiên 'isEmpty()', sau đó một phép thử 'null' trong' ofNullable'. Không cần thử nghiệm thứ hai: 'return testList.isEmpty()? Optional.empty(): Optional.of (testList.stream() mapToDouble (v -> v) .average(). GetAsDouble()); ' – Holger

+3

Tôi nghĩ về nó, nhưng tôi đặc biệt đặt hoạt động ba bên trong' Tùy chọn. ofNullable'. Đó là điều phong cách hơn, trong khi tôi đồng ý rằng nó có một hoạt động so sánh hơn – Andremoniy

4

một biến thể nhẹ trên @Andremoniy's answer là bỏ qua DoubleStream và sử dụng averagingDouble() thu:

if (testList.isEmpty()) { 
    return Optional.empty(); 
} 
return Optional.of(testList.stream().collect(Collector.averagingDouble())); 

Hoặc xem xét liệu 0 là một giá trị trả về giá trị trong một danh sách rỗng, và p ossibly bỏ qua hoàn toàn Optional hoàn toàn.

Các vấn đề liên quan