Menyaring Koleksi Java mengikut Senarai

1. Gambaran keseluruhan

Menyaring Koleksi mengikut Senarai adalah senario logik perniagaan yang biasa. Terdapat banyak cara untuk mencapainya. Walau bagaimanapun, ada yang menyebabkan penyelesaian yang tidak berfungsi jika tidak dilakukan dengan betul.

Dalam tutorial ini, kami akan membandingkan beberapa pelaksanaan penyaringan dan membincangkan kelebihan dan kekurangannya .

2. Menggunakan Gelung Untuk Setiap

Kita akan mulakan dengan sintaks paling klasik, gelung untuk setiap.

Untuk ini dan semua contoh lain dalam artikel ini, kami akan menggunakan kelas berikut:

public class Employee { private Integer employeeNumber; private String name; private Integer departmentId; //Standard constructor, getters and setters. }

Kami juga akan menggunakan kaedah berikut untuk semua contoh, demi kesederhanaan:

private List buildEmployeeList() { return Arrays.asList( new Employee(1, "Mike", 1), new Employee(2, "John", 1), new Employee(3, "Mary", 1), new Employee(4, "Joe", 2), new Employee(5, "Nicole", 2), new Employee(6, "Alice", 2), new Employee(7, "Bob", 3), new Employee(8, "Scarlett", 3)); } private List employeeNameFilter() { return Arrays.asList("Alice", "Mike", "Bob"); }

Sebagai contoh, kami akan menyaring senarai Pekerja pertama berdasarkan senarai kedua dengan nama Pekerja untuk mencari hanya Pekerja yang mempunyai nama tertentu.

Sekarang, mari kita lihat pendekatan tradisional - mengulangi kedua-dua senarai mencari perlawanan:

@Test public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingForEachLoop() { List filteredList = new ArrayList(); List originalList = buildEmployeeList(); List nameFilter = employeeNameFilter(); for (Employee employee : originalList) { for (String name : nameFilter) { if (employee.getName().equals(name)) { filteredList.add(employee); // break; } } } assertThat(filteredList.size(), is(nameFilter.size())); }

Ini adalah sintaks sederhana, tetapi cukup verbose, dan sebenarnya tidak cekap. Ringkasnya, iterasi melalui produk Cartesian dari dua set untuk mendapatkan jawapan kami.

Bahkan menambah jeda untuk keluar lebih awal akan tetap dilakukan pada pesanan yang sama dengan produk Cartesian dalam keadaan biasa.

Jika kita panggil saiz senarai pekerja n, kemudian nameFilter akan di perintah itu juga kuat, memberikan kita satu (n2) O klasifikasi.

3. Menggunakan Aliran dan Senarai # mengandungi

Kami sekarang akan memfaktorkan semula kaedah sebelumnya dengan menggunakan lambdas untuk mempermudah sintaksis dan meningkatkan pembacaan . Mari juga gunakan kaedah List # berisi sebagai penapis lambda :

@Test public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambda() { List filteredList; List originalList = buildEmployeeList(); List nameFilter = employeeNameFilter(); filteredList = originalList.stream() .filter(employee -> nameFilter.contains(employee.getName())) .collect(Collectors.toList()); assertThat(filteredList.size(), is(nameFilter.size())); }

Dengan menggunakan API Aliran , kebolehbacaan telah bertambah baik, tetapi kod kami tetap tidak cekap seperti kaedah kami sebelumnya kerana masih berulang melalui produk Cartesian secara dalaman . Oleh itu, kita mempunyai klasifikasi O (n2) yang sama .

4. Menggunakan Aliran dengan HashSet

Untuk meningkatkan prestasi, kita mesti menggunakan kaedah HashSet # berisi . Kaedah ini berbeza dengan senarai # yang mengandungi kerana ia melakukan carian kod hash , memberi kami jumlah operasi yang tetap:

@Test public void givenEmployeeList_andNameFilterList_thenObtainFilteredEmployeeList_usingLambdaAndHashSet() { List filteredList; List originalList = buildEmployeeList(); Set nameFilterSet = employeeNameFilter().stream().collect(Collectors.toSet()); filteredList = originalList.stream() .filter(employee -> nameFilterSet.contains(employee.getName())) .collect(Collectors.toList()); assertThat(filteredList.size(), is(nameFilterSet.size())); }

Dengan menggunakan HashSet, kecekapan kod kami telah jauh meningkat sementara tidak mempengaruhi kebolehbacaan. Oleh kerana HashSet # mengandungi jalan dalam masa yang berterusan, kami telah meningkatkan klasifikasi kami kepada O (n).

5. Kesimpulan

Dalam tutorial ringkas ini, kami belajar bagaimana menyaring Koleksi berdasarkan Senarai nilai dan kelemahan menggunakan kaedah yang mungkin kelihatan seperti kaedah yang paling mudah.

Kita mesti sentiasa mempertimbangkan kecekapan kerana kod kita mungkin berjalan dalam kumpulan data yang besar, dan masalah prestasi boleh membawa bencana dalam persekitaran seperti itu.

Semua kod yang disajikan dalam artikel ini boleh didapati di GitHub.