來源:blog.csdn.net/qq_41698074/article/details/108502976
前言
雖然 stream在 Java8 中就已經被引入,但是大多數人卻沒有去使用這個十分有用的特性,本文就通過介紹幾個通過使用stream讓代碼更簡潔、可讀,來讓你了解stream的方便之處,
技巧
陣列轉集合
相信經常刷LeetCode的小伙伴,偶爾會遇到需要將List與基本型別陣列進行互轉的情況,然后就需要寫像下面這樣的代碼:
// 將 List 元素存盤到陣列中
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
int[] arr = new int[list.size()];
Integer[] temp = list.toArray(new Integer[0]);
for (int i = 0; i < temp.length; i++) {
arr[i] = temp[i];
}
// 將陣列元素 存盤到 List 中
int[] arr = {1, 2, 3, 4, 5};
List<Integer> list = new ArrayList<>();
for (int val : arr) {
list.add(val);
}
以上兩個轉換雖然寫著還不算麻煩,但是每次都需要寫一個回圈,尤其在陣列轉List的時候還需要使用一個臨時陣列,都會讓人看著很不舒服,但是如果使用了stream就會大不一樣,用stream實作了相同功能的代碼如下:
// 將 List 元素存盤到陣列中
List<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5));
int[] arr = list.stream().mapToInt(Integer::intValue).toArray();
// 將陣列元素 存盤到 List 中
int[] arr = {1, 2, 3, 4, 5};
List<Integer> list = IntStream.of(arr).boxed().collect(Collectors.toList());
可以發現通過使用stream,我們能夠在寫代碼的時候更加連貫,代碼也更加可靠易維護,注意力也可以放在業務功能上,相信各位就算對lambda語法并不是太熟悉,在閱讀上面代碼的時候,也很容易能夠看懂,
統計陣列元素中的個數
假設我們現在需要統計并輸出一個有重復元素的陣列中每個元素及對應元素出現的個數,相信各位都能夠想到,我們使用一個Map就很容易解決這個問題,代碼如下:
String[] arr = {"a", "c", "a", "b", "d", "c"};
Map<String, Integer> map = new HashMap<>();
for (String s : arr) {
if (map.containsKey(s)) {
map.put(s, map.get(s) + 1);
} else {
map.put(s, 1);
}
}
map.forEach((key, value) -> System.out.println(key + " : " + value));
如果對Map中的API更加熟悉的小伙伴,可能會寫出下面這個更加簡潔的代碼:
String[] arr = {"a", "c", "a", "b", "d", "c"};
Map<String, Integer> map = new HashMap<>();
for (String s : arr) {
map.put(s, map.getOrDefault(s, 0) + 1);
}
map.forEach((key, value) -> System.out.println(key + " : " + value));
但是,如果使用stream,我們還能寫出更加簡潔的代碼,同樣不需要寫煩人的回圈了,而且只需兩行代碼即可(為了提高可讀性,進行了換行):
String[] arr = {"a", "c", "a", "b", "d", "c"};
Stream.of(arr)
.collect(Collectors.toMap(k -> k, k -> 1, Integer::sum))
.forEach((k, v) -> System.out.println(k + " : " + v));
注意
在上面的代碼中,Collectors.toMap(k -> k, k -> 1, Integer::sum)這一部分可能不好理解,對于這里面的三個引數,第一個引數代表將arr中的每一個元素作為Map中的key,第二個引數代表每一個key所對應的value,在這里每一個元素都對應個數1,第三個引數代表,如果存在相同的key,該如何進行合并,這里通過使用Integer::sum,代表將具有相同key的元素進行合并時,其value進行相加,這樣便實作了每個元素個數的統計,
基本資料型別的陣列自定義排序
有時我們會遇到對基本資料型別的陣列進行自定義排序的情況,不同于包裝型別的陣列和集合可以直接使用比較器,我們只能通過將基本陣列型別的陣列轉為包裝型別或者存盤在集合中,在排序完成后再轉為基本型別的陣列,再者,我們只能通過手寫排序演算法,修改排序演算法中的比較進行實作,
不管是哪種方法,我們都沒辦法將精力放在邏輯功能上,必須寫一些額外的代碼,甚至是修改底層邏輯,就像下面的代碼一樣(實作陣列逆序):
int[] arr = {1, 5, 9, 7, 2, 3, 7, -1, 0, 3};
// 將陣列轉為包裝型別再進行自定義排序
Integer[] temp = new Integer[arr.length];
for (int i = 0; i < arr.length; i++) {
temp[i] = arr[i];
}
Arrays.sort(temp, Comparator.reverseOrder());
for (int i = 0; i < temp.length; i++) {
arr[i] = temp[i];
}
// 將陣列轉為集合型別再進行自定義排序
List<Integer> list = new ArrayList<>();
for (int val : arr) {
list.add(val);
}
list.sort(Collections.reverseOrder());
for (int i = 0; i < list.size(); i++) {
arr[i] = list.get(i);
}
// 通過手寫排序演算法修改比較規則實作
// 為了讓代碼更加簡潔,使用了最暴力且沒有優化的冒泡排序
int[] arr = {1, 5, 9, 7, 2, 3, 7, -1, 0, 3};
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] < arr[j + 1]) {
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
可以發現以上幾種方法,我們都需要寫很多代碼,無法將注意力集中在設計自定義排序這個問題上,但是通過使用stream,我們就可以寫出下面這樣簡潔的代碼(如果愿意的話,你也可以把一系列的鏈式操作寫在一行上,但為了代碼的可讀性,不建議那么做):
int[] arr = {1, 5, 9, 7, 2, 3, 7, -1, 0, 3};
arr = IntStream.of(arr)
.boxed()
.sorted(Comparator.reverseOrder())
.mapToInt(Integer::intValue)
.toArray();
注意
在這里其實為了實作陣列的逆序,我們只需要呼叫Arrays的sort方法,然后再進行陣列元素的反轉即可,不過因為是為了講解自定義排序,大多數情況下不會是陣列逆序這么簡單,所以我就寫了更加通用一些的代碼,
統計陣列中前 k 個個高頻元素
在最后,我們通過一道題來進行實戰以便更好的體驗stream的強大之處,當然我們在練習該題的時候,更需要從演算法的角度去考慮該題的解法,不過在本文,我們主要為了講解stream的使用,所以就不去考慮演算法的東西了,而如果使用stream,我們就可以寫出下面這樣簡單易懂的代碼:
class Solution {
public int[] topKFrequent(int[] nums, int k) {
return Arrays.stream(nums)
.boxed()
.collect(Collectors.toMap(e -> e, e -> 1, Integer::sum))
.entrySet()
.stream()
.sorted((m1, m2) -> m2.getValue() - m1.getValue())
.limit(k)
.mapToInt(Map.Entry::getKey)
.toArray();
}
}
總結
本文介紹了幾個簡單、實用的stream使用技巧,當然stream的應用遠不止此,希望通過本文,能夠激發起你學習stream的興趣,本文若有錯誤之處,也歡迎你的指正,
近期熱文推薦:
1.1,000+ 道 Java面試題及答案整理(2022最新版)
2.勁爆!Java 協程要來了,,,
3.Spring Boot 2.x 教程,太全了!
4.別再寫滿屏的爆爆爆炸類了,試試裝飾器模式,這才是優雅的方式!!
5.《Java開發手冊(嵩山版)》最新發布,速速下載!
覺得不錯,別忘了隨手點贊+轉發哦!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/546031.html
標籤:Java
