使用 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 上取得。