與Map一起使用流
1.簡介
在本教程中,我們將討論一些有關如何使用Java Stream
的示例。 與Map
一起使用。值得注意的是,其中一些練習可以使用雙向Map
數據結構解決,但我們對功能方法感興趣。
首先,我們說明將用於Maps
和Stream
的基本思想。然後,我們提出了幾個與Maps
及其使用Stream
的具體解決方案有關的不同問題。
2.基本思想
要注意的主要事情是Stream是元素的序列,可以很容易地從Collection
獲得。
Maps
具有不同的結構,從鍵到值的映射沒有順序。這並不意味著我們無法將Map
結構轉換為不同的序列,從而使我們無法自然地使用Stream API。
讓我們看看從Map
獲取不同Collection
的方法,然後可以將其轉換為Stream
:
Map<String, Integer> someMap = new HashMap<>();
我們可以獲得一組鍵值對:
Set<Map.Entry<String, Integer>> entries = someMap.entrySet();
我們還可以獲取與Map
關聯的密鑰集:
Set<String> keySet = someMap.keySet();
或者我們可以直接使用一組值:
Collection<Integer> values = someMap.values();
這些都為我們提供了一個從它們那裡獲取流來處理這些集合的入口點:
Stream<Map.Entry<String, Integer>> entriesStream = entries.stream();
Stream<Integer> valuesStream = values.stream();
Stream<String> keysStream = keySet.stream();
3.使用Stream
獲取Map
的鍵
3.1。輸入數據
假設我們有一個Map
:
Map<String, String> books = new HashMap<>();
books.put(
"978-0201633610", "Design patterns : elements of reusable object-oriented software");
books.put(
"978-1617291999", "Java 8 in Action: Lambdas, Streams, and functional-style programming");
books.put("978-0134685991", "Effective Java");
我們有興趣為標題為“ Effective Java”的書找到ISBN。
3.2。檢索比賽
由於書名在我們的Map
不存在,因此我們希望能夠指出沒有相關的ISBN。我們可以使用**Optional
** to express that
:
在此示例中,假設我們對與該書名匹配的書的任何鍵感興趣:
Optional<String> optionalIsbn = books.entrySet().stream()
.filter(e -> "Effective Java".equals(e.getValue()))
.map(Map.Entry::getKey)
.findFirst();
assertEquals("978-0134685991", optionalIsbn.get());
讓我們分析一下代碼。首先,如先前所見,我們從Map
獲取entrySet
。
我們只考慮標題為“ Effective Java”的條目,因此第一個中間操作將是過濾器。
我們對整個Map
條目不感興趣,但對每個條目的鍵都不感興趣。因此,下一個鏈接的中間操作就是這樣做的:這是一個map
操作,它將生成一個新的流作為輸出,其中將僅包含與我們要查找的標題匹配的條目的鍵。
**因為我們只想要一個結果,所以我們可以應用findFirst()
**終端操作,該操作將在Stream
提供初始值作為Optional
對象。
讓我們看一個標題不存在的情況:
Optional<String> optionalIsbn = books.entrySet().stream()
.filter(e -> "Non Existent Title".equals(e.getValue()))
.map(Map.Entry::getKey).findFirst();
assertEquals(false, optionalIsbn.isPresent());
3.3。檢索多個結果
現在讓我們更改問題,看看如何處理返回多個結果而不是一個結果。
要返回多個結果,讓我們將以下書籍添加到Map
:
books.put("978-0321356680", "Effective Java: Second Edition");
因此,現在,如果我們查找all
以“ Effective Java”開頭的書籍,我們將獲得不止一個結果:
List<String> isbnCodes = books.entrySet().stream()
.filter(e -> e.getValue().startsWith("Effective Java"))
.map(Map.Entry::getKey)
.collect(Collectors.toList());
assertTrue(isbnCodes.contains("978-0321356680"));
assertTrue(isbnCodes.contains("978-0134685991"));
在這種情況下,我們要做的是替換過濾條件,以驗證Map
的值是否以“ Effective Java”開頭,而不是比較String
相等性。
這次,我們collect
結果-而不是挑選第一個-將匹配項放入List
。
4.使用Stream
獲取Map
的值
現在,讓我們在一個不同的問題與地圖的工作重點:與其獲得的ISBNs
基礎上, titles
,我們會嘗試並獲得titles
基礎上ISBNs.
讓我們使用原始的Map
。我們想找到其ISBN以“ 978-0”開頭的標題。
List<String> titles = books.entrySet().stream()
.filter(e -> e.getKey().startsWith("978-0"))
.map(Map.Entry::getValue)
.collect(Collectors.toList());
assertEquals(2, titles.size());
assertTrue(titles.contains(
"Design patterns : elements of reusable object-oriented software"));
assertTrue(titles.contains("Effective Java"));
該解決方案類似於針對先前問題的解決方案–我們先對條目集進行流處理,然後進行過濾,映射和收集。
和以前一樣,如果我們只想返回第一個匹配項,則可以在map
方法調用findFirst()
方法之後,而不是將所有結果收集在List
。
5.結論
我們已經展示瞭如何以功能方式處理Map
.
特別是,我們已經看到,一旦切換到對Map
使用關聯的集合,使用Stream
的處理就變得更加容易和直觀。
而且,當然,所有示例都可以在GitHub項目中找到。