具有Lambda表達式的Java流過濾器
1.簡介
在本快速教程中,我們將探討在Java中使用Streams
時Stream.filter()
方法的使用。
我們將研究如何使用它,以及如何處理帶有已檢查異常的特殊情況。
2.使用Stream.filter()
filter()
方法是Stream
接口的中間操作,它使我們可以過濾與給定Predicate:
匹配的流元素Predicate:
Stream<T> filter(Predicate<? super T> predicate)
要查看其工作原理,讓我們創建一個Customer
類:
public class Customer {
private String name;
private int points;
//Constructor and standard getters
}
另外,讓我們創建一個客戶集合:
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<Customer> customers = Arrays.asList(john, sarah, charles, mary);
2.1。篩選集合
filter()
方法的一個常見用例是處理集合。
讓我們列出100 points.
以上的客戶points.
為此,我們可以使用lambda表達式:
List<Customer> customersWithMoreThan100Points = customers
.stream()
.filter(c -> c.getPoints() > 100)
.collect(Collectors.toList());
我們還可以使用方法參考,它是lambda表達式的縮寫:
List<Customer> customersWithMoreThan100Points = customers
.stream()
.filter(Customer::hasOverHundredPoints)
.collect(Collectors.toList());
在這種情況下,我們將hasOverHundredPoints
方法添加到我們的Customer
類中:
public boolean hasOverHundredPoints() {
return this.points > 100;
}
在這兩種情況下,我們都得到相同的結果:
assertThat(customersWithMoreThan100Points).hasSize(2);
assertThat(customersWithMoreThan100Points).contains(sarah, charles);
2.2。使用多個條件過濾集合
此外,我們可以對filter()
使用多個條件。例如,我們可以按points
和name
過濾:
List<Customer> charlesWithMoreThan100Points = customers
.stream()
.filter(c -> c.getPoints() > 100 && c.getName().startsWith("Charles"))
.collect(Collectors.toList());
assertThat(charlesWithMoreThan100Points).hasSize(1);
assertThat(charlesWithMoreThan100Points).contains(charles);
3.處理異常
到目前為止,我們一直在使用不會引發異常的謂詞的過濾器。實際上, Java中的功能接口不會聲明任何檢查或未檢查的異常。
接下來,我們將展示一些不同的方法來處理lambda表達式中的異常。
3.1。使用自定義包裝
首先,我們首先向我們的Customer
添加一個profilePhotoUrl
:
private String profilePhotoUrl;
另外,讓我們添加一個簡單的hasValidProfilePhoto()
方法來檢查配置文件的可用性:
public boolean hasValidProfilePhoto() throws IOException {
URL url = new URL(this.profilePhotoUrl);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
return connection.getResponseCode() == HttpURLConnection.HTTP_OK;
}
我們可以看到hasValidProfilePhoto()
方法拋出IOException
。現在,如果我們嘗試使用這種方法過濾客戶:
List<Customer> customersWithValidProfilePhoto = customers
.stream()
.filter(Customer::hasValidProfilePhoto)
.collect(Collectors.toList());
我們將看到以下錯誤:
Incompatible thrown types java.io.IOException in functional expression
為了處理它,我們可以使用的替代方法之一是用try-catch塊包裝它:
List<Customer> customersWithValidProfilePhoto = customers
.stream()
.filter(c -> {
try {
return c.hasValidProfilePhoto();
} catch (IOException e) {
//handle exception
}
return false;
})
.collect(Collectors.toList());
如果需要從謂詞中引發異常,則可以將其包裝在未經檢查的異常中,例如RuntimeException
。
3.2。使用ThrowingFunction
另外,我們可以使用ThrowingFunction庫。
ThrowingFunction是一個開放源代碼庫,允許我們處理Java功能接口中的已檢查異常。
首先,將throwing-function
依賴項添加到pom中:
<dependency>
<groupId>pl.touk</groupId>
<artifactId>throwing-function</artifactId>
<version>1.3</version>
</dependency>
為了處理謂詞中的異常,該庫為我們提供了ThrowingPredicate
類,該類具有unchecked()
方法來包裝已檢查的異常。
讓我們看看它的作用:
List customersWithValidProfilePhoto = customers
.stream()
.filter(ThrowingPredicate.unchecked(Customer::hasValidProfilePhoto))
.collect(Collectors.toList());
4。結論
在本文中,我們看到了一個如何使用filter()
方法處理流的示例。我們還探討了一些處理異常的替代方法。
與往常一樣,完整的代碼可以在GitHub上找到。