2015-10-23 13 views
12

Tôi thường thấy mình cần lọc Stream hoặc sử dụng biến vị ngữ để kiểm tra xem một trường nhất định có một giá trị đã cho hay không.Có phương pháp tiện lợi nào để tạo ra một Predicate để kiểm tra xem một trường có bằng một giá trị nhất định không?

Nói ví dụ tôi có POJO này:

public class A { 
    private Integer field; 

    public A(final Integer field) { 
     this.field = field; 
    } 

    public Integer getField() { 
     return field; 
    } 
} 

Và tôi muốn lọc một Stream của các đối tượng dựa trên giá trị của field:

final Integer someValue = 42; 
    Stream.of(new A(42), new A(1729), new A(42), new A(87539319), new A(null)) 
      .filter(a -> Objects.equals(a.getField(), someValue)) 
      ... 

Nên có một phương pháp thuận tiện để tạo vị từ cho phương thức filter? Tôi nhận thấy có Predicate.isEqual nhưng nó không phù hợp với nhu cầu.

tôi có thể khá dễ dàng viết một như thế này:

public static <T,R> Predicate<T> isEqual(Function<? super T, ? extends R> f, R value) { 
    return v -> Objects.equals(value, f.apply(v)); 
} 

và sử dụng nó như:

Stream.of(new A(42), new A(1729), new A(42), new A(87539319), new A(null)) 
      .filter(isEqual(A::getField, someValue)) 
      ... 

nhưng tôi muốn để tái sử dụng một phương pháp hiện tại từ JDK nếu có thể.

+5

Không phải là tôi biết. Nhưng lưu ý rằng nếu bạn biết rằng 'someValue' không phải là' null', thì một 'a -> someValue.equals (a.getField())' đơn giản là đủ. Nó không tệ hơn 'isEqual (A :: getField, someValue)' đối với tôi, đặc biệt nếu tôi cho rằng 'A' đúng hơn là' NameOfARealLifeClass'… – Holger

Trả lời

8

Không có phương thức nhà máy được xây dựng như vậy, bạn có thể dễ dàng kiểm tra bằng cách xem all usages of Predicate within the JFC và tìm "Phương pháp trong ... trả về Predicate". Ngoài các phương thức trong phạm vi Predicate, chỉ có Pattern.asPredicate() trả về một số Predicate.

Trước khi bạn định triển khai phương thức nhà máy như vậy, bạn nên tự hỏi mình có thực sự đáng giá không. Điều làm cho biểu thức lambda của bạn ở dạng .filter(a -> Objects.equals(a.getField(), someValue)) trông phức tạp, là việc sử dụng Objects.equals, điều này là không cần thiết khi bạn có thể dự đoán ít nhất một đối số cho dù đó là null. Kể từ đây, someValue là không bao giờ null, bạn có thể đơn giản hóa biểu thức:

final Integer someValue = 42; 
Stream.of(new A(42), new A(1729), new A(42), new A(87539319), new A(null)) 
    .filter(a -> someValue.equals(a.getField())) 
    … 

Nếu bạn vẫn muốn thực hiện phương pháp nhà máy và giành chiến thắng một giá cho một cách sáng tạo sử dụng những gì đã có, bạn có thể sử dụng:

public static <T,R> Predicate<T> isEqual(Function<? super T, ? extends R> f, R value) { 
    return f.andThen(Predicate.isEqual(value)::test)::apply; 
} 

Tuy nhiên, đối với mã sản xuất, tôi thà khuyên một thực hiện như thế này:

public static <T,R> Predicate<T> isEqual(Function<? super T, ? extends R> f, R value) { 
    return value==null? t -> f.apply(t)==null: t -> value.equals(f.apply(t)); 
} 

này yếu tố ra kiểm tra xem các con stant là null để đơn giản hóa hoạt động sẽ được thực hiện trong mỗi bài kiểm tra. Vì vậy, nó vẫn không cần Objects.equals. Lưu ý rằng Predicate.isEqual cũng tương tự.

+0

bạn có thể giải thích tại sao 'value == null ?. ..'-giải pháp là thích hợp hơn 'Objects.equals'? – Roland

+0

@Roland: khi bạn gọi 'Objects.equals' trong mọi đánh giá chức năng, bạn sẽ kiểm tra lại hiệu quả liệu' giá trị' là 'null' trong mọi đánh giá chức năng mặc dù nó sẽ không thay đổi. Rõ ràng, hiệu ứng sẽ lớn nhất * nếu * 'giá trị' là' null', vì hàm kết quả 't -> f.apply (t) == null' sẽ rẻ hơn nhiều so với' Objects.equals'. Như bạn có thể sử dụng một phương pháp tiện ích như vậy rất nhiều thời gian ở những nơi khác nhau, các hiệu ứng tích tụ.Như đã nói, ['Predicate.isEqual' tương tự] (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/function/Predicate.java # 114) – Holger

+0

Cảm ơn bạn đã làm rõ! Ôi trời ... đó là lý do tại sao tôi đã rút ra giá trị ngay từ đầu ... đã đến lúc cuối tuần rồi. – Roland

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