2014-05-01 21 views
12

Java 8 có một số lớp tùy chọn, như OptionalDouble, OptionalInt, OptionalLong.Thao tác trên Java 8 Giá trị tùy chọn *.

Có cách nào hoạt động tốt với các giá trị tùy chọn cùng loại không? Tức là, tôi muốn có thể làm:

OptionalDouble d1 = OptionalDouble.of(1.); 
OptionalDouble d2 = OptionalDouble.of(2.); 
OptionalDouble d3 = OptionalDouble.of(3.); 

OptionalDouble result = d1.add(d2).multiply(d3); 

Và tất nhiên nếu có bất kỳ kết quả nào "trống" thì kết quả sẽ trống. Sau khi googling xung quanh một chút, tôi tìm thấy một vài mẫu mã mà mọi người đang sử dụng các chức năng đó (ví dụ: add) nhưng nó không phải là một phần của API (nữa?).

Trả lời

3

Lạ. Tài liệu tham khảo Optional có phương thức map mà bạn có thể sử dụng để làm điều gì đó tương tự với những gì bạn muốn, nhưng dường như không có các tùy chọn nguyên thủy. Tôi tin rằng truy vấn duy nhất của bạn hiện tại là sử dụng OptionalDouble::isPresent hoặc OptionalDouble::ifPresent.

Hoặc bạn có thể xác định trình trợ giúp của riêng mình add phương pháp hoặc xác định lớp học OptionalDouble của riêng bạn để bao gồm các phương pháp đó.

+2

'Tùy chọn # Bản đồ' có vẻ như cần' Hàm', không phải là 'BinaryOperator', vì vậy nó chỉ hoạt động với các hàm hoạt động trên một giá trị, không phải là' add' hoặc 'multiply'. – ajb

+0

Tôi đã sử dụng một phương pháp trợ giúp nhưng tôi không thực sự hiểu lý do tại sao họ bỏ qua các phương pháp này, hoặc ít nhất là khả năng thêm chúng.Lưu ý rằng các lớp 'Optional' cho các kiểu nguyên thủy như' OptionalDouble' là 'final' để chúng không thể được mở rộng. – siki

+1

@siki Chúng là cuối cùng vì các tùy chọn là các lớp bất biến và do đó không bao giờ được mở rộng, vì bạn không thể đảm bảo bất biến nữa sau đó nếu một phương thức nhận tham số 'OptionalDouble'. – skiwi

3

Bạn có thể thực hiện của riêng bạn đóng gói một OptionalDouble, một điều rất quan trọng ở đây để xem xét là lớp đóng gói của bạn nên không thay đổi để ngăn chặn sự nhầm lẫn là OptionalDouble chính nó là không thay đổi.

Thực hiện riêng được ưu tiên hơn phương pháp tĩnh để dễ đọc.

tôi đã đi trước và tạo riêng tôi, với các hành vi cơ bản nhất càng tốt:

public class OptionalDoubleImproved { 
    private static final OptionalDoubleImproved EMPTY = OptionalDoubleImproved.of(OptionalDouble.empty()); 

    private final OptionalDouble optionalDouble; 

    private OptionalDoubleImproved(final OptionalDouble optionalDouble) { 
     this.optionalDouble = Objects.requireNonNull(optionalDouble); 
    } 

    public static OptionalDoubleImproved of(final OptionalDouble optionalDouble) { 
     return new OptionalDoubleImproved(optionalDouble); 
    } 

    public OptionalDoubleImproved applyFunction(final DoubleBinaryOperator operator, final OptionalDouble operand) { 
     Objects.requireNonNull(operator); 
     Objects.requireNonNull(operand); 
     if (!optionalDouble.isPresent() || !operand.isPresent()) { 
      return EMPTY; 
     } 
     return OptionalDoubleImproved.of(OptionalDouble.of(operator.applyAsDouble(optionalDouble.getAsDouble(), operand.getAsDouble()))); 
    } 

    public OptionalDouble get() { 
     return optionalDouble; 
    } 

    @Override 
    public int hashCode() { 
     int hash = 7; 
     hash = 53 * hash + Objects.hashCode(this.optionalDouble); 
     return hash; 
    } 

    @Override 
    public boolean equals(Object obj) { 
     if (obj == null) { 
      return false; 
     } 
     if (getClass() != obj.getClass()) { 
      return false; 
     } 
     final OptionalDoubleImproved other = (OptionalDoubleImproved) obj; 
     if (!Objects.equals(this.optionalDouble, other.optionalDouble)) { 
      return false; 
     } 
     return true; 
    } 

    @Override 
    public String toString() { 
     return "OptionalDoubleImproved[" + optionalDouble + "]"; 
    } 
} 

Mà sau đó có thể được sử dụng như:

OptionalDouble d1 = OptionalDouble.of(1.); 
OptionalDouble d2 = OptionalDouble.of(2.); 
OptionalDouble d3 = OptionalDouble.of(3.); 

OptionalDouble result = OptionalDoubleImproved.of(d1) 
     .applyFunction((a, b) -> a + b, d2) 
     .applyFunction((a, b) -> a * b, d3) 
     .get(); 
2

Tôi sẽ sử dụng đồng bằng double

double d1 = 1, d2 = 2, d3 = 3; 
if (condition) 
    d1 = Double.NaN; 
double result = (d1 + d2) * d3; // if any double is NaN, the result is NaN 

Không chỉ nhanh hơn và ngắn hơn, nó cũng đơn giản hơn.

3

Mục đích chính của Optional là để đại diện cho chức năng của return value that might be absent.

Điểm có chuyên môn hóa ban đầu của luồng là tránh chi phí đấm bốc/mở hộp. Với OptionalInt và bạn bè có một cấp độ không thể tránh khỏi của boxing (sẽ tồi tệ hơn nếu họ không tồn tại, vì thay thế sẽ là Optional<Integer>), nhưng mục đích là cho bất cứ ai xử lý giá trị trả về để bỏ hộp nó ngay lập tức (hoặc cung cấp mặc định hoặc ném một ngoại lệ nếu nó vắng mặt) và sau đó đối phó với các nguyên thủy thực tế từ đó trở đi.

Hỗ trợ tất cả các API bổ sung để thực hiện các phép tính số học, so sánh, v.v. trên các nguyên thủy tùy chọn sẽ thêm nhiều bloat API hơn nữa. Sử dụng nó sẽ dẫn đến lộn xộn, mã chậm, khá bất lợi so với cú pháp biểu thức số học hoàn hảo tốt đã tồn tại trong Java. Tóm lại, việc thêm một loạt các hoạt động vào các nguyên thủy tùy chọn không được coi là hữu ích.

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