Saya ingin memeriksa apakah suatu List
berisi objek yang memiliki bidang dengan nilai tertentu. Sekarang, saya bisa menggunakan loop untuk memeriksa dan memeriksa, tetapi saya ingin tahu apakah ada kode yang lebih efisien.
Sesuatu seperti;
if(list.contains(new Object().setName("John"))){
//Do some stuff
}
Saya tahu kode di atas tidak melakukan apa-apa, hanya untuk menunjukkan secara kasar apa yang saya coba capai.
Juga, hanya untuk memperjelas, alasan saya tidak ingin menggunakan loop sederhana adalah karena kode ini saat ini akan masuk ke dalam loop yang ada di dalam loop yang berada di dalam loop. Agar mudah dibaca, saya tidak ingin terus menambahkan loop ke loop ini. Jadi saya bertanya-tanya apakah ada alternatif (ish) sederhana.
equals(Object)
metode objek kustom Anda?for(Person p:list) if (p.getName().equals("John") return true; return false;
Saya tidak akan menemukan cara yang lebih ringkas di Jawa.p.equals(p)
harus selalu benar, jadi saya bingung apa yang ingin Anda capai. Semoga jika Anda mengajukan pertanyaan baru Anda bisa mendapatkan bantuan yang lebih baik.Jawaban:
Streaming
Jika Anda menggunakan Java 8, mungkin Anda bisa mencoba sesuatu seperti ini:
Atau sebagai alternatif, Anda dapat mencoba sesuatu seperti ini:
Metode ini akan kembali
true
jikaList<MyObject>
berisiMyObject
dengan namaname
. Jika Anda ingin melakukan operasi pada setiapMyObject
s itugetName().equals(name)
, maka Anda dapat mencoba sesuatu seperti ini:Dimana
o
mewakili sebuahMyObject
instance.Atau, seperti komentar yang disarankan (Terima kasih MK10), Anda dapat menggunakan
Stream#anyMatch
metode ini:sumber
public boolean
. Juga, Anda mungkin ingin menggunakanObjects.equals()
jikao.getName()
bisanull
.null
pemeriksaan, bukan hanya satu (milik saya).return list.stream().anyMatch(o -> o.getName().equals(name));
java.util.Objects
untuk perbandingan nullsafe.return list.stream().anyMatch(o -> Objects.euqals(o.getName(), name);
Jika Anda ingin memeriksa objek dalam aliran untuk null, Anda dapat menambahkan.filter(Objects::nonNull)
sebelum anyMatch.Anda punya dua pilihan.
1. Pilihan pertama, yang lebih disukai, adalah mengganti metode `equals ()` di kelas Object Anda.
Katakanlah, misalnya, Anda memiliki kelas Obyek ini:
Sekarang katakanlah Anda hanya peduli dengan nama MyObject, bahwa itu harus unik sehingga jika dua `MyObject` memiliki nama yang sama mereka harus dianggap sama. Dalam hal ini, Anda ingin mengganti metode `equals ()` (dan juga metode `hashcode ()`) sehingga membandingkan nama untuk menentukan kesetaraan.
Setelah melakukan ini, Anda dapat memeriksa untuk melihat apakah Koleksi berisi MyObject dengan nama "foo" dengan seperti:
Namun, ini mungkin bukan pilihan bagi Anda jika:
Jika salah satu dari ini adalah masalahnya, Anda akan menginginkan opsi 2:
2. Tulis metode utilitas Anda sendiri:
Atau, Anda dapat memperluas ArrayList (atau koleksi lain) dan kemudian menambahkan metode Anda sendiri ke dalamnya:
Sayangnya tidak ada cara yang lebih baik di sekitarnya.
sumber
Google Jambu
Jika Anda menggunakan Jambu Biji , Anda dapat mengambil pendekatan fungsional dan melakukan hal berikut
yang terlihat sedikit bertele-tele. Namun predikat adalah objek dan Anda dapat memberikan varian berbeda untuk pencarian yang berbeda. Perhatikan bagaimana perpustakaan itu sendiri memisahkan iterasi koleksi dan fungsi yang ingin Anda terapkan. Anda tidak perlu mengganti
equals()
untuk perilaku tertentu.Seperti disebutkan di bawah ini, kerangka java.util.Stream dibangun ke dalam Java 8 dan kemudian menyediakan sesuatu yang serupa.
sumber
Iterables.any(list, predicate)
, yang praktis sama, dan Anda mungkin atau mungkin tidak suka secara gaya.Ini adalah bagaimana melakukannya menggunakan Java 8+:
sumber
Collection.contains()
diimplementasikan dengan memanggilequals()
setiap objek sampai satu kembalitrue
.Jadi salah satu cara untuk mengimplementasikan ini adalah dengan menimpanya
equals()
tetapi tentu saja, Anda hanya dapat memiliki satu yang sama.Kerangka kerja seperti Jambu karena itu menggunakan predikat untuk ini. Dengan
Iterables.find(list, predicate)
, Anda dapat mencari bidang yang berubah-ubah dengan memasukkan tes ke dalam predikat.Bahasa lain yang dibangun di atas VM memiliki built in ini. Di Groovy , misalnya, Anda cukup menulis:
Java 8 membuat hidup kami lebih mudah, juga:
Jika Anda peduli dengan hal-hal seperti ini, saya sarankan buku "Beyond Java". Ini berisi banyak contoh untuk banyak kekurangan di Jawa dan bagaimana bahasa lain melakukan lebih baik.
sumber
equals()
ini sangat terbatas. Ini berarti memeriksa "identitas objek" - apa pun artinya bagi beberapa kelas objek. Jika Anda menambahkan bendera bidang mana yang harus dimasukkan, yang dapat menyebabkan semua jenis masalah. Saya sangat menyarankan untuk tidak melakukannya.def result = list.find{ it.name == 'John' }
Oracle / JCP harus dituntut karena kejahatan perang terhadap programmer.Pencarian Biner
Anda dapat menggunakan Collections.binarySearch untuk mencari elemen dalam daftar Anda (dengan asumsi daftar diurutkan):
yang akan mengembalikan angka negatif jika objek tidak ada dalam koleksi atau yang lain akan mengembalikan
index
objek. Dengan ini, Anda dapat mencari objek dengan strategi pencarian berbeda.sumber
Peta
Anda bisa membuat
Hashmap<String, Object>
menggunakan salah satu nilai sebagai kunci, dan kemudian melihat apakahyourHashMap.keySet().contains(yourValue)
mengembalikan true.sumber
Koleksi Eclipse
Jika Anda menggunakan Eclipse Collections , Anda dapat menggunakan
anySatisfy()
metode ini. Baik menyesuaikanList
dalam AndaListAdapter
atau mengubah AndaList
menjadiListIterable
jika mungkin.Jika Anda akan sering melakukan operasi seperti ini, lebih baik mengekstrak metode yang menjawab apakah tipe tersebut memiliki atribut.
Anda dapat menggunakan formulir alternatif
anySatisfyWith()
bersama-sama dengan referensi metode.Jika Anda tidak dapat mengubah Anda
List
menjadi aListIterable
, inilah cara Anda akan menggunakannyaListAdapter
.Catatan: Saya pengendara untuk Eclipse ollections.
sumber
Predicate
Jika Anda tidak menggunakan Java 8, atau pustaka yang memberi Anda lebih banyak fungsi untuk menangani koleksi, Anda bisa mengimplementasikan sesuatu yang bisa lebih dapat digunakan kembali daripada solusi Anda.
Saya menggunakan sesuatu seperti itu, saya memiliki antarmuka predikat, dan saya meneruskan implementasinya ke kelas util saya.
Apa keuntungan melakukan ini dengan cara saya? Anda memiliki satu metode yang berhubungan dengan pencarian dalam koleksi jenis apa pun. dan Anda tidak perlu membuat metode terpisah jika Anda ingin mencari berdasarkan bidang yang berbeda. Yang perlu Anda lakukan adalah memberikan predikat berbeda yang dapat dihancurkan segera setelah tidak lagi berguna /
jika Anda ingin menggunakannya, yang perlu Anda lakukan hanyalah memanggil metode dan menentukan predikat Anda
sumber
Berikut ini solusi menggunakan Jambu Biji
sumber
contains
Metode menggunakanequals
internal. Jadi Anda perlu menggantiequals
metode untuk kelas Anda sesuai kebutuhan Anda.Tapi ini tidak benar secara sintaksis:
sumber
this
.equals
kasus penggunaan tunggal, kecuali jika masuk akal untuk kelas secara umum. Anda akan jauh lebih baik hanya menulis perulangan.Jika Anda perlu melakukan ini
List.contains(Object with field value equal to x)
berulang kali, solusi sederhana dan efisien adalah:Maka
List.contains(Object with field value equal to x)
hasilnya akan sama denganfieldOfInterestValues.contains(x);
sumber
Anda juga dapat
anyMatch()
menggunakan:sumber
Meskipun ada JAVA 8 SDK, ada banyak alat koleksi yang dapat membantu perpustakaan Anda bekerja, misalnya: http://commons.apache.org/proper/commons-collections/
sumber