Penapis Aliran Java dengan Lambda Expression

1. Pengenalan

Dalam tutorial ringkas ini, kita akan meneroka penggunaan kaedah Stream.filter () ketika kita bekerja dengan Stream di Java.

Kami akan melihat bagaimana menggunakannya, dan bagaimana menangani kes khas dengan pengecualian yang diperiksa.

2. Menggunakan Stream.filter ()

Kaedah penapis () adalah operasi perantaraan antara muka Aliran yang membolehkan kita menyaring elemen aliran yang sesuai dengan Predikat tertentu :

Stream filter(Predicate predicate)

Untuk melihat bagaimana ini berfungsi, mari buat kelas Pelanggan :

public class Customer { private String name; private int points; //Constructor and standard getters }

Sebagai tambahan, mari buat koleksi pelanggan:

Customer john = new Customer("John P.", 15); Customer sarah = new Customer("Sarah M.", 200); Customer charles = new Customer("Charles B.", 150); Customer mary = new Customer("Mary T.", 1); List customers = Arrays.asList(john, sarah, charles, mary);

2.1. Menapis Koleksi

Kes penggunaan umum kaedah penapis () adalah memproses koleksi.

Mari buat senarai pelanggan dengan lebih dari 100 mata. Untuk melakukannya, kita boleh menggunakan ungkapan lambda:

List customersWithMoreThan100Points = customers .stream() .filter(c -> c.getPoints() > 100) .collect(Collectors.toList());

Kita juga dapat menggunakan rujukan kaedah, yang merupakan singkatan dari ungkapan lambda:

List customersWithMoreThan100Points = customers .stream() .filter(Customer::hasOverHundredPoints) .collect(Collectors.toList());

Dalam kes ini, kami menambahkan kaedah hasOverHundredPoints ke kelas Pelanggan kami :

public boolean hasOverHundredPoints() { return this.points > 100; }

Dalam kedua kes tersebut, kami mendapat hasil yang sama:

assertThat(customersWithMoreThan100Points).hasSize(2); assertThat(customersWithMoreThan100Points).contains(sarah, charles);

2.2. Menyaring Koleksi dengan Pelbagai Kriteria

Selanjutnya, kita boleh menggunakan pelbagai keadaan dengan penapis () . Sebagai contoh, kita dapat menapis mengikut titik dan nama :

List charlesWithMoreThan100Points = customers .stream() .filter(c -> c.getPoints() > 100 && c.getName().startsWith("Charles")) .collect(Collectors.toList()); assertThat(charlesWithMoreThan100Points).hasSize(1); assertThat(charlesWithMoreThan100Points).contains(charles);

3. Mengendalikan Pengecualian

Sehingga kini, kami telah menggunakan penapis dengan predikat yang tidak memberikan pengecualian. Sesungguhnya, antara muka fungsional di Java tidak menyatakan pengecualian yang dicentang atau tidak dicentang .

Seterusnya kita akan menunjukkan beberapa cara yang berbeza untuk menangani pengecualian dalam ungkapan lambda.

3.1. Menggunakan Pembungkus Tersuai

Pertama, kita akan mulakan dengan menambahkan profilPhotoUrl kepada Pelanggan kami :

private String profilePhotoUrl;

Sebagai tambahan, mari kita tambahkan kaedah hasValidProfilePhoto () sederhana untuk memeriksa ketersediaan profil:

public boolean hasValidProfilePhoto() throws IOException { URL url = new URL(this.profilePhotoUrl); HttpsURLConnection connection = (HttpsURLConnection) url.openConnection(); return connection.getResponseCode() == HttpURLConnection.HTTP_OK; }

Kita dapat melihat bahawa kaedah hasValidProfilePhoto () membuang IOException . Sekarang jika kita cuba menapis pelanggan dengan kaedah ini:

List customersWithValidProfilePhoto = customers .stream() .filter(Customer::hasValidProfilePhoto) .collect(Collectors.toList());

Kami akan melihat ralat berikut:

Incompatible thrown types java.io.IOException in functional expression

Untuk mengatasinya, salah satu alternatif yang dapat kita gunakan adalah membungkusnya dengan blok cubaan:

List customersWithValidProfilePhoto = customers .stream() .filter(c -> { try { return c.hasValidProfilePhoto(); } catch (IOException e) { //handle exception } return false; }) .collect(Collectors.toList());

Sekiranya kita perlu membuang pengecualian dari predikat kita, kita dapat membungkusnya dengan pengecualian yang tidak dicentang seperti RuntimeException .

3.2. Menggunakan ThrowingFunction

Sebagai alternatif, kita boleh menggunakan perpustakaan ThrowingFunction.

ThrowingFunction adalah perpustakaan sumber terbuka yang membolehkan kita menangani pengecualian yang diperiksa dalam antara muka fungsional Java.

Mari mulakan dengan menambahkan kebergantungan fungsi lemparan ke pom kami:

 pl.touk throwing-function 1.3 

Untuk menangani pengecualian dalam predikat, perpustakaan ini menawarkan kami kelas ThrowingPredicate , yang mempunyai kaedah () yang tidak dicentang untuk membungkus pengecualian yang dicentang.

Mari kita lihat dalam tindakan:

List customersWithValidProfilePhoto = customers .stream() .filter(ThrowingPredicate.unchecked(Customer::hasValidProfilePhoto)) .collect(Collectors.toList());

4. Kesimpulan

Dalam artikel ini, kami melihat contoh cara menggunakan kaedah filter () untuk memproses aliran. Kami juga meneroka beberapa alternatif untuk menangani pengecualian.

Seperti biasa, kod lengkap boleh didapati di GitHub.