Java中Stream流的使用示例詳解
在 Java 中,Stream 流是 Java 8 引入的一個強大特性,它允許你以聲明式的方式處理集合數(shù)據(jù)。Stream 流提供了一種高效且易于使用的方式來對數(shù)據(jù)進(jìn)行過濾、映射、排序、聚合等操作,使代碼更加簡潔和可讀。
1. 獲取Stream流
要使用Stream流首先要獲取到Stream流
public static void main(String[] args) {
//創(chuàng)建Stream流
//1. 單列集合創(chuàng)建
List<String> list = new ArrayList<>();
Stream<?> stream1 = list.stream();
Set<String> set = new HashSet<>();
Stream<?> stream2 = set.stream();
Stack<String> stack = new Stack<>();
Stream<?> stream3 = stack.stream();
Queue<String> queue = new LinkedList<>();
Stream<?> stream4 = stack.stream();
//2. 雙列集合創(chuàng)建
Map<String, String> map = new HashMap<>();
Stream<?> stream5 = map.entrySet().stream();
//3. 數(shù)組創(chuàng)建
int[] arr = {1, 2 ,3};
IntStream stream6 = Arrays.stream(arr);
//4. 零散數(shù)據(jù)創(chuàng)建
Stream<?> stream7 = Stream.of(1, 2, 3, 4);
}注意 Stream.of(T... values) values為變長參數(shù)可以接收一個數(shù)組,但是這里只能接收引用類型的數(shù)組,如果是基礎(chǔ)類型的數(shù)據(jù)由于不會自動裝包會把整個數(shù)組視為一個數(shù)據(jù)
2. 中間方法
當(dāng)我們獲取到Stream流后就可以調(diào)用其中的一些方法來對其中的數(shù)據(jù)進(jìn)行一些操作,其中的方法分為兩大類,其一就是中間方法,中間方法的特點是會返回一個新的 Stream 流,允許你鏈?zhǔn)秸{(diào)用多個操作 :
- Stream<T> filter(Predicate<T>):過濾滿足條件的元素。
- Stream<T> limit(long):限制元素數(shù)量。
- Stream<T> skip(long):跳過前 n 個元素。
- Stream<T> distinct():去重。
- static<T> Stream<T> concat(Stream,Stream ):合并a和兩個流作為一個流
- Stream<T> sorted():排序。
- Stream<T> map(Function<T, R>):將元素轉(zhuǎn)換為另一種類型。
注意:
- 每個Stream流只能使用一次,中間方法返回的是一個新的Stream流
- 修改Stream流中的數(shù)據(jù)不會影響原來集合或數(shù)組中的數(shù)據(jù)
2.1 filter使用示例
filter方法接收一個Predicate類型的參數(shù),我們轉(zhuǎn)到其定義:

可以看到這是一個函數(shù)式接口, 同時test方法的描述也說明了,如果參數(shù)匹配則返回true否則返回false,這里的含義即為,如果該數(shù)據(jù)(t)是符合要求的則通過,否則不通過:
public static void filterTest() {
List<String> list = new ArrayList<>();
Collections.addAll(list, "張明", "張三豐", "張良", "張明朱諾", "楊過", "小龍女");
//這里篩選以張開頭且長度為3的字符串
list.stream()
.filter(s -> s.startsWith("張"))
.filter(s -> s.length() == 3)
.forEach(x-> System.out.print(x + " "));
}這里我們使用lambad表達(dá)式重寫test方法,先賽選了以張開頭的數(shù)據(jù),再賽選了長度為3的數(shù)據(jù)最后使用forEach輸出
2.2 limit 和skip使用
limit接收一個long類型的參數(shù)表示只保留前n個元素,skip同樣接收一個long類型的參數(shù)表示要跳過前n個元素:
public static void limitAndSkipTest() {
List<String> list = new ArrayList<>();
Collections.addAll(list, "張明", "張三豐", "張良", "張明朱諾", "楊過", "小龍女");
System.out.println("limit:");
list.stream()
.limit(4)
.forEach(x-> System.out.print(x + " "));
System.out.println("\nskip:");
list.stream()
.skip(3)
.forEach(x-> System.out.print(x + " "));
System.out.println("\nlimit-skip:");
list.stream()
.limit(4)
.skip(3)
.forEach(x-> System.out.print(x + " "));
System.out.println("\nskip-limit:");
list.stream()
.skip(3)
.limit(4)
.forEach(x-> System.out.print(x + " "));
}運行結(jié)果:

2.3 distinct 和concat
public static void distinctAndConcatTest() {
List<String> list1 = new ArrayList<>();
Collections.addAll(list1, "張三豐", "張三豐", "楊過", "張明朱諾", "楊過", "小龍女");
List<String> list2 = new ArrayList<>();
Collections.addAll(list2, "張明", "張三豐", "迪迦");
System.out.println("\ndistinct:");
list1.stream()
.distinct()
.forEach(x-> System.out.print(x + " "));
System.out.println("\nconcat:");
Stream.concat(list1.stream(), list2.stream())
.forEach(x-> System.out.print(x + " "));
}運行結(jié)果:

2.4 stored使用
public static void sortedTest() {
List<String> list1 = new ArrayList<>();
Collections.addAll(list1, "張明", "張三豐", "迪迦");
List<Integer> list2 = new ArrayList<>();
Collections.addAll(list2, 1, 2, 3);
System.out.println("\nsortedList1:");
list1.stream()
.sorted()
.forEach(x-> System.out.print(x + " "));
System.out.println("\nsortedList2:");
list2.stream()
.sorted()
.forEach(x-> System.out.print(x + " "));
System.out.println("\nsortedList2desc:");
list2.stream()
.sorted(((o1, o2) -> o2 - o1))
.forEach(x-> System.out.print(x + " "));
}sorted不傳參數(shù)時默認(rèn)是排降序,可以傳入比較器自定義排序規(guī)則
2.5 map使用
public static void MapTest() {
List<String> list1 = new ArrayList<>();
Collections.addAll(list1, "張明-16", "張三豐-23", "迪迦-3000");
//獲取每個人的年齡
/**
* 第一個參數(shù)對應(yīng)原本的數(shù)據(jù)類型,第二個參數(shù)代表要轉(zhuǎn)成的數(shù)據(jù)類型
*/
list1.stream().map(new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return Integer.parseInt(s.split("-")[1]);
}
}).forEach(x-> System.out.print(x + " "));
System.out.println();
//使用lambada表達(dá)式
list1.stream()
.map(s -> Integer.parseInt(s.split("-")[1]))
.forEach(x-> System.out.print(x + " "));
}運行結(jié)果:

3. 終結(jié)方法
可以理解為結(jié)束方法,不會再返回Stream流
常用的終結(jié)方法有:
- forEach(Consumer<T>):遍歷每個元素。
- count():計算元素數(shù)量。
- toArray():將元素轉(zhuǎn)換為數(shù)組。
- collect(Collector<T, A, R>):將元素收集到集合中。
3.1 forEach/count/toArray()使用
public static void CountAndToArrayTest() {
List<String> list1 = new ArrayList<>();
Collections.addAll(list1, "張三豐", "張三豐", "楊過", "張明朱諾", "楊過", "小龍女");
List<Integer> list2 = new ArrayList<>();
Collections.addAll(list2, 1, 2, 3);
System.out.println(list1.stream().count());
System.out.println(list2.stream().count());
//<>為需要創(chuàng)建的數(shù)組的類型
String[] str = list1.stream().toArray(new IntFunction<String[]>() {
@Override
public String[] apply(int value) {
//value代表數(shù)據(jù)的數(shù)量,我們返回一個長度大于等于value的數(shù)據(jù)即可
return new String[value];
}
});
System.out.println(Arrays.toString(str));
//使用lambada表達(dá)式
Integer[] arr = list2.stream().toArray(value -> new Integer[value]);
System.out.println(Arrays.toString(arr));
}3.2 collect 使用
將流中的元素收集到集合中
public static void CollectTest() {
List<String> list1 = new ArrayList<>();
Collections.addAll(list1, "張三豐-男-23", "楊過-男-32", "張三豐-男-23", "張明朱諾-女-19", "小龍女-女-18");
//收集所有男性
//List
List<String> list = list1.stream()
.filter(s -> "男".equals(s.split("-")[1]))
.collect(Collectors.toList());
System.out.println(list);
//Set
Set<String> set = list1.stream()
.filter(s -> "男".equals(s.split("-")[1]))
.collect(Collectors.toSet());
System.out.println(set);
//Map
//收集男性,名字作為鍵,年齡作為值
Map<String, Integer> map1 = list1.stream()
.filter(s -> "男".equals(s.split("-")[1]))
.distinct()//map中key不能重復(fù),所以先去重
.collect(Collectors.toMap(
new Function<String, String>() {
@Override
public String apply(String s) {
return s.split("-")[0];
}
},
new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return Integer.parseInt(s.split("-")[2]);
}
}
));
System.out.println(map1);
//使用lambada表達(dá)式
Map<String, Integer> map2 = list1.stream()
.filter(s -> "男".equals(s.split("-")[1]))
.distinct()//map中key不能重復(fù),所以先去重
.collect(Collectors.toMap(
s -> s.split("-")[0],
s -> Integer.parseInt(s.split("-")[2])
));
System.out.println(map2);
}這里特別說明toMap()方法,

可以看到toMap接收兩個Function做為參數(shù),這里通過參數(shù)名我們不難猜出,一個作為鍵,一個作為值,于是我們只需實現(xiàn)Function接口重寫其中方法使其返回預(yù)期的鍵/值即可。
到此這篇關(guān)于Java中Stream流的使用的文章就介紹到這了,更多相關(guān)java stream流使用內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Mybatis使用useGeneratedKeys獲取自增主鍵
這篇文章主要為大家介紹了Mybatis使用useGeneratedKeys獲取自增主鍵示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
簡單聊一聊Java線程池ThreadPoolExecutor
在使用線程池之后,開啟線程就變成了在線程池當(dāng)中找到一個空閑的線程,銷毀線程變成了歸還線程到線程池的過程,下面這篇文章主要給大家介紹了關(guān)于Java線程池ThreadPoolExecutor的相關(guān)資料,需要的朋友可以參考下2022-06-06
Java Swing實現(xiàn)讓窗體居中顯示的方法示例
這篇文章主要介紹了Java Swing實現(xiàn)讓窗體居中顯示的方法,結(jié)合實例形式分析了swing使用setBounds方法控制窗口布局的相關(guān)操作技巧,需要的朋友可以參考下2017-11-11
SpringBoot中Mybatis注解一對多和多對多查詢實現(xiàn)示例
這篇文章主要介紹了SpringBoot中Mybatis注解一對多和多對多查詢的實現(xiàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03

