Bagaimana cara memeriksa apakah elemen ada menggunakan ekspresi lambda?

118

Secara khusus, saya memiliki TabPane, dan saya ingin tahu apakah ada elemen dengan ID tertentu di dalamnya.

Jadi, saya ingin melakukan ini dengan ekspresi lambda di Jawa:

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

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

Jawaban:

273

Coba gunakan anyMatchLambda Expression. Itu adalah pendekatan yang jauh lebih baik.

 boolean idExists = tabPane.getTabs().stream()
            .anyMatch(t -> t.getId().equals(idToCheck));
Masudul
sumber
11
Juga diperhatikan: jika Anda ingin meniadakan penggunaan cek noneMatchbukan anyMatch.
Blacklight
Panggilan memerlukan API level 24
FabioLux
50

Meskipun jawaban yang diterima benar, saya akan menambahkan versi yang lebih elegan (menurut saya):

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

Jangan mengabaikan penggunaan Stream # map () yang memungkinkan untuk meratakan struktur data sebelum menerapkan Predicate.

jFrenetic
sumber
3
apa yang lebih baik di sini? Saya hanya melihat satu operasi lagi. Maaf, saya baru mengenal lamba ini.
TecHunter
2
@TecHunter lebih eksplisit. Bayangkan Anda membaca kode ini untuk pertama kali, atau lagi setelah beberapa saat. Ada beberapa keuntungan: Pertama, kami langsung menunjukkan bahwa kami sebenarnya tidak tertarik pada tab, tetapi beberapa memetakannya. Kedua, dengan menggunakan referensi metode (yang hanya mungkin karena kami memecah lambda awal menjadi dua langkah) kami menunjukkan bahwa tidak ada kejutan yang disembunyikan dalam kode. Ketiga, dengan menggunakan referensi metode, kita tidak membuat Predikat baru, tetapi benar-benar hanya digunakan kembali equals. Meskipun, memang, contoh di sini sangat sederhana, tetapi saya harap Anda mengerti maksud saya.
Malte Hartwig
@MalteHartwig terima kasih! ya saya mendapatkan 3 poin Anda tetapi saya bertanya tentang perataan dengan map, apakah langkah pemrosesan lain tidak? Saya akan mencoba membandingkan 2 metode :)
TecHunter
1
@MalteHartwig diuji dalam 10kk ArrayList dengan objek sederhana yang mencoba menemukan elemen terakhir. memberikan perbedaan 2ms 131ms melawan 133ms untuk Anda. pada daftar larik 1kk milik Anda jika lebih cepat dengan 2ms (55ms hingga 53ms). Jadi kami dapat mengatakan bahwa milik Anda lebih baik :)
TecHunter
2
Getter @TecHunter sangat murah. Selalu lebih suka kejelasan kode daripada menyimpan ekstra 2 milidetik (meskipun, saya ragu hasilnya akurat, mungkin berfluktuasi di setiap proses). Selain itu, ingatlah bahwa operasi perantara pada aliran (seperti map) pada dasarnya malas . Artinya, getIdmetode tersebut tidak diterapkan pada setiap elemen koleksi. Ini dievaluasi dengan malas sampai anyMatchmengembalikan nilai true .
jFrenetic
3

Jawaban di atas mengharuskan Anda untuk malloc objek aliran baru.

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))) {
   ...
}
kevinarpe
sumber