Làm cách nào để kiểm tra xem phần tử có tồn tại hay không bằng cách sử dụng biểu thức lambda?


118

Cụ thể, tôi có TabPane và tôi muốn biết liệu có phần tử với ID cụ thể trong đó hay không.

Vì vậy, tôi muốn làm điều này với biểu thức lambda trong Java:

boolean idExists = false;
String idToCheck = "someId";

for (Tab t : tabPane.getTabs()){
    if(t.getId().equals(idToCheck)) {
        idExists = true;
    }
}

Câu trả lời:


273

Cố gắng sử dụng anyMatchLambda Expression. Đó là cách tiếp cận tốt hơn nhiều.

 boolean idExists = tabPane.getTabs().stream()
            .anyMatch(t -> t.getId().equals(idToCheck));

11
Cũng cần lưu ý: nếu bạn muốn phủ định việc sử dụng séc noneMatchthay vì anyMatch.
Blacklight

Cuộc gọi yêu cầu API cấp 24
FabioLux

50

Mặc dù câu trả lời được chấp nhận là đúng, nhưng tôi sẽ thêm một phiên bản thanh lịch hơn (theo ý kiến ​​của tôi):

boolean idExists = tabPane.getTabs().stream()
    .map(Tab::getId)
    .anyMatch(idToCheck::equals);

Đừng bỏ qua việc sử dụng Stream # map () cho phép làm phẳng cấu trúc dữ liệu trước khi áp dụng Predicate.


3
cái gì tốt hơn ở đây? Tôi chỉ thấy một thao tác nữa. Xin lỗi, tôi mới làm quen với thứ lamba này.
TecHunter

2
@TecHunter nó rõ ràng hơn. Hãy tưởng tượng bạn đọc mã này lần đầu tiên hoặc một lúc sau mới đọc lại. Có một số ưu điểm: Đầu tiên, chúng tôi ngay lập tức cho thấy rằng chúng tôi không thực sự quan tâm đến tab, mà là một số ánh xạ của nó. Thứ hai, bằng cách sử dụng tham chiếu phương thức (điều này chỉ có thể thực hiện được vì chúng tôi chia lambda ban đầu thành hai bước), chúng tôi cho thấy rằng không có bất ngờ nào ẩn trong mã. Thứ ba, bằng cách sử dụng các tham chiếu phương thức, chúng tôi không tạo một Predicate mới mà chỉ thực sự sử dụng lại equals. Mặc dù, được, ví dụ ở đây rất đơn giản, nhưng tôi hy vọng bạn hiểu ý tôi.
Malte Hartwig

@MalteHartwig xin cảm ơn! vâng, tôi nhận được 3 điểm của bạn nhưng tôi đã hỏi về việc làm phẳng với map, nó có một bước xử lý khác không? Tôi sẽ thử so sánh 2 phương pháp :)
TecHunter

1
@MalteHartwig đã thử nghiệm trong ArrayList 10kk với một đối tượng đơn giản đang cố gắng tìm phần tử cuối cùng. mang lại sự khác biệt 2ms 131ms so với 133ms cho bạn. trên danh sách mảng 1kk của bạn nếu nhanh hơn 2ms (55ms đến 53ms). Vì vậy, chúng tôi có thể nói rằng của bạn tốt hơn :)
TecHunter

2
@TecHunter getters có giá siêu rẻ. Luôn thích sự rõ ràng của mã hơn là tiết kiệm thêm 2 mili giây (mặc dù tôi nghi ngờ kết quả là chính xác, nó có thể dao động trên mỗi lần chạy). Bên cạnh đó, hãy nhớ rằng các hoạt động trung gian trên các luồng (chẳng hạn như map) về bản chất là lười biếng . Điều đó có nghĩa là getIdphương pháp đó không được áp dụng cho từng phần tử của tập hợp. Nó được đánh giá một cách lười biếng cho đến khi anyMatchtrả về true .
jFrenetic

3

Các câu trả lời trên yêu cầu bạn phân bổ một đối tượng luồng mới.

public <T>
boolean containsByLambda(Collection<? extends T> c, Predicate<? super T> p) {

    for (final T z : c) {
        if (p.test(z)) {
            return true;
        }
    }
    return false;
}

public boolean containsTabById(TabPane tabPane, String id) {
    return containsByLambda(tabPane.getTabs(), z -> z.getId().equals(id));
}
...
if (containsTabById(tabPane, idToCheck))) {
   ...
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.