使用 Java Streams 修改和列印清單項目
1. 概述
當我們使用 Java 時,操作清單是一項基本技能。
在本快速教程中,我們將探索修改或轉換清單然後在 Java 中列印其元素的不同方法。
2. 修改和列印列表
列印元素清單對我們來說並不是一個挑戰。例如,我們可以在forEach()
方法中呼叫列印操作:
List<String> theList = Lists.newArrayList("Kai", "Liam", "Eric", "Kevin");
theList.forEach(element -> log.info(element));
在上面的程式碼中,我們使用 SLF4J 記錄器來輸出給定列表中的元素。當我們執行程式碼時,我們可以看到控制台中印了四個名字:
Kai
Liam
Eric
Kevin
如果我們打算在列印清單中的元素之前修改它們,我們可以使用List.replaceAll()
方法。
接下來,讓我們將theList
中的每個String
元素轉換為大寫並在測試方法中列印修改後的值:
List<String> theList = Lists.newArrayList("Kai", "Liam", "Eric", "Kevin");
theList.replaceAll(element -> element.toUpperCase());
theList.forEach(element -> log.info(element));
assertEquals(List.of("KAI", "LIAM", "ERIC", "KEVIN"), theList);
正如我們所看到的,我們在replaceAll()
方法中使用lambda表達式來執行大小寫轉換。運行測試後,我們可以在控制台看到大寫的值:
KAI
LIAM
ERIC
KEVIN
值得注意的是, replaceAll()
方法要求列表物件是可變列表,例如上面程式碼中使用的Arraylist
。如果清單是不可變UnsupportedOperationException
,例如Collection.singletonList()
和List.of()
傳回的清單對象,則該方法將會拋出UnsupportedOperationException 。
因此,在實際場景中,通常最好將原始列表轉換為新列表,而不是直接修改它。接下來,我們來探討如何轉換清單並有效率地無縫輸出其元素。
3. 使用 Stream API 轉換和列印列表
Java 8 中引入的 Stream API 顯著改變了我們處理物件集合的方式。流提供了一種聲明性和功能性的資料處理方法,提供了一種簡潔而富有表現力的方式來對集合執行操作。
例如,我們可以將列表作為來源,使用map()
方法轉換流中的元素,然後使用forEachOrdered()
列印元素,如下所示:
theList.stream()
.map(... <the transformation logic> ...)
.forEachOrdered( ... <print the element> ...)
程式碼非常簡單。但是,要注意的是Stream.forEachOrdered()
是一個終端操作。這個終端操作本質上標誌著流管道的結束。因此,呼叫此方法後,流物件將變得不可存取。此限制意味著後續的流程操作(例如收集轉換後的元素)不再可行。
因此,我們希望透過不同的方法來實現我們的目標,這種方法允許我們繼續在流上執行操作。
一個簡單的想法是在map()
中包含列印方法呼叫:
List<String> theList = List.of("Kai", "Liam", "Eric", "Kevin");
List<String> newList = theList.stream()
.map(element -> {
String newElement = element.toUpperCase();
log.info(newElement);
return newElement;
})
.collect(Collectors.toList());
assertEquals(List.of("KAI", "LIAM", "ERIC", "KEVIN"), newList);
這樣,列印流並不會終止流管道,之後我們仍然可以執行Collector
操作。當然,轉換後的元素會印在控制台中:
KAI
LIAM
ERIC
KEVIN
然而,這種方法的一個缺點是它不必要地向map()
方法添加了不相關的邏輯。接下來,我們使用peek()
方法來改進它:
List<String> theList = List.of("Kai", "Liam", "Eric", "Kevin");
List<String> newList = theList.stream()
.map(element -> element.toUpperCase())
.peek(element -> log.info(element))
.collect(Collectors.toList());
assertEquals(List.of("KAI", "LIAM", "ERIC", "KEVIN"), newList);
與forEachOrdered()
不同, peek()
是一個中間運算。它對流中的每個元素執行提供的操作並返回流。因此,我們可以在呼叫peek()
後向流管道添加進一步的操作,例如上面程式碼中的collect()
。
peek()
方法接受Consumer
實例作為參數。在我們的範例中,我們將 lambda 表達式作為Consumer
傳遞給peek().
當我們運行這個測試時,它通過了,並且預期的輸出被印到控制台:
KAI
LIAM
ERIC
KEVIN
4。結論
在本文中,我們首先示範如何使用replaceAll()
+ forEach()
方法修改和列印清單。然後,我們探討如何使用 Stream API 來轉換和列印流中的元素。
與往常一樣,範例的完整原始程式碼可在 GitHub 上取得。