1. 程式人生 > 實用技巧 >恕我直言你可能真的不會java第12篇-如何使用Stream API對Map型別元素排序

恕我直言你可能真的不會java第12篇-如何使用Stream API對Map型別元素排序

在這篇文章中,您將學習如何使用Java對Map進行排序。前幾日有位朋友面試遇到了這個問題,看似很簡單的問題,但是如果不仔細研究一下也是很容易讓人懵圈的面試題。所以我決定寫這樣一篇文章。在Java中,有多種方法可以對Map進行排序,但是我們將重點介紹Java 8 Stream,這是實現目標的一種非常優雅的方法。

一、什麼是Java 8 Stream

使用Java 8 Streams,我們可以按鍵和按值對對映進行排序。下面是它的工作原理:

  1. 將Map或List等集合類物件轉換為Stream物件
  2. 使用Streams的sorted()方法對其進行排序
  3. 最終將其返回為LinkedHashMap(可以保留排序順序)

sorted()方法以aComparator作為引數,從而可以按任何型別的值對Map進行排序。如果對Comparator不熟悉,可以看本號前幾天的文章,有一篇文章專門介紹了使用Comparator對List進行排序。

二、學習一下HashMap的merge()函式

在學習Map排序之前,有必要講一下HashMap的merge()函式,該函式應用場景就是當Key重複的時候,如何處理Map的元素值。這個函式有三個引數:

  • 引數一:向map裡面put的鍵
  • 引數二:向map裡面put的值
  • 引數三:如果鍵發生重複,如何處理值。可以是一個函式,也可以寫成lambda表示式。
        String k = "key";
HashMap<String, Integer> map = new HashMap<String, Integer>() {{
put(k, 1);
}};
map.merge(k, 2, (oldVal, newVal) -> oldVal + newVal);

看上面一段程式碼,我們首先建立了一個HashMap,並往裡面放入了一個鍵值為k:1的元素。當我們呼叫merge函式,往map裡面放入k:2鍵值對的時候,k鍵發生重複,就執行後面的lambda表示式。表示式的含義是:返回舊值oldVal加上新值newVal(1+2),現在map裡面只有一項元素那就是k:3。

其實lambda表示式很簡單:表示匿名函式,箭頭左側是引數,箭頭右側是函式體。函式的引數型別和返回值,由程式碼上下文來確定。

三、按Map的鍵排序

下面一個例子使用Java 8 Stream按Map的鍵進行排序:

// 建立一個Map,並填入資料
Map<String, Integer> codes = new HashMap<>();
codes.put("United States", 1);
codes.put("Germany", 49);
codes.put("France", 33);
codes.put("China", 86);
codes.put("Pakistan", 92); // 按照Map的鍵進行排序
Map<String, Integer> sortedMap = codes.entrySet().stream()
.sorted(Map.Entry.comparingByKey())
.collect(
Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(oldVal, newVal) -> oldVal,
LinkedHashMap::new
)
); // 將排序後的Map列印
sortedMap.entrySet().forEach(System.out::println);

看上文中第二段程式碼:

  • 首先使用entrySet().stream() 將Map型別轉換為Stream流型別。
  • 然後使用sorted方法排序,排序的依據是Map.Entry.comparingByKey(),也就是按照Map的鍵排序
  • 最後用collect方法將Stream流轉成LinkedHashMap。 其他引數都好說,重點看第三個引數,就是一個merge規則的lambda表示式,與merge方法的第三個引數的用法一致。由於本例中沒有重複的key,所以新值舊值隨便返回一個即可。

上面的程式將在控制檯上列印以下內容,鍵(國家/地區名稱)以自然字母順序排序:

China=86
France=33
Germany=49
Pakistan=92
United States=1

請注意使用LinkedHashMap來儲存排序的結果以保持順序。預設情況下,Collectors.toMap()返回HashMapHashMap不能保證元素的順序。

如果希望按照鍵進行逆向排序,加入下圖中紅色部分程式碼即可。

四、按Map的值排序

當然,您也可以使用Stream API按其值對Map進行排序:

Map<String, Integer> sortedMap2 = codes.entrySet().stream()
.sorted(Map.Entry.comparingByValue())
.collect(Collectors.toMap(
Map.Entry::getKey,
Map.Entry::getValue,
(oldVal, newVal) -> oldVal,
LinkedHashMap::new)); sortedMap2.entrySet().forEach(System.out::println);

這是顯示Map按值排序的輸出:

United States=1
France=33
Germany=49
China=86
Pakistan=92

五、使用TreeMap按鍵排序

大家可能都知道TreeMap內的元素是有順序的,所以利用TreeMap排序也是可取的一種方法。您需要做的就是建立一個TreeMap物件,並將資料從HashMapput到TreeMap中,非常簡單:

// 將 `HashMap` 轉為 `TreeMap`
Map<String, Integer> sorted = new TreeMap<>(codes);

這是輸出:

China=86
France=33
Germany=49
Pakistan=92
United States=1

如上所示,鍵(國家/地區名稱)以自然字母順序排序。

歡迎關注我的部落格,裡面有很多精品合集

  • 本文轉載註明出處(必須帶連線,不能只轉文字):字母哥部落格

覺得對您有幫助的話,幫我點贊、分享!您的支援是我不竭的創作動力! 。另外,筆者最近一段時間輸出瞭如下的精品內容,期待您的關注。