日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java0steam_Java学习 - Stream 使用

發布時間:2023/12/10 java 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java0steam_Java学习 - Stream 使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Java Stream使用

這段時間在學數據庫和Java,發現Java的Stream實際上和數據庫的查詢操作非常類似。這里簡單介紹Stream的用法,并和Sql Server中的操作聯系起來。

此文為初學Stream所寫,以后對Stream有更深的理解后會重寫

當我們使用一個流的時候,通常包括三個基本步驟:

獲取一個數據源(source)

數據轉換

執行操作獲取想要的結果

每次轉換原有 Stream 對象不改變,返回一個新的 Stream 對象(可以有多次轉換),這就允許對其操作可以像鏈條一樣排列,變成一個管道,如下圖所示。

一、創建 stream

有多種方式生成 Stream Source:

從 Collection 和數組

Collection.stream()

Collection.parallelStream()

Arrays.stream(T array) or Stream.of()

從 BufferedReader

java.io.BufferedReader.lines()

靜態工廠

java.util.stream.IntStream.range()

java.nio.file.Files.walk()

自己構建

java.util.Spliterator

其它

Random.ints()

BitSet.stream()

Pattern.splitAsStream(java.lang.CharSequence)

JarFile.stream()

創建Stream示例

// 1. Individual values

Stream stream = Stream.of("a", "b", "c");

// 2. Arrays

String [] strArray = new String[] {"a", "b", "c"};

stream = Stream.of(strArray);

stream = Arrays.stream(strArray);

// 3. Collections

List list = Arrays.asList(strArray);

stream = list.stream();

二、stream 操作

stream的操作分為兩大類,一類為中間操作,一類為終端操作。

中間操作:返回值仍然為一個流,不會消耗流

終端操作:返回最終結果;終端操作會消耗掉流,使之不再可用

1.stream.filter()

stream.filter() 是一個中間操作

stream.filter()用于對stream進行某種篩選,stream.filter() 相當于Sql server 中,from ... where ...

在filter()中應當給出篩選條件,準確的說,應該實現Predicate接口,這個接口將被應用于stream中的每一個元素,判斷其是否應該被包含在結果stream中。

這個接口只有一個抽象方法待用戶實現

抽象方法應該返回一個布爾值,當布爾值為真時,stream.filter()將這個元素包含在結果stream中

stream.filter()使用示例:創建Integer流,然后篩選出偶數

ArrayList arrlist = new ArrayList();

Stream st = arrlist.stream();

Stream st2 = st.filter(new Predicate() {

@Override

public boolean test(Integer arg0) {

return arg0 % 2 == 0;

}

});

還可以用lambda表達式來實現

ArrayList arrlist = new ArrayList();

Stream st = arrlist.stream();

Stream st2 = st.filter((o1)->(o1 % 2 == 0));

關于Predicate接口,它還有.and(),.or(),.negate(),.isEqual()四個默認方法,這里不多介紹。但這些方法也十分常用,對于稍微復雜一點的邏輯就需要使用。

使用Precicate接口需要導入

import java.util.function.Predicate;

2.stream.map()

stream.map()是一個中間操作

stream.map()用于對stream進行某種映射,stream.map() 相當于Sql server 中,select

雖然這么說不太恰當,因為Sql sever 的select實際上時 SQL語言中 \(\sigma , \prod\)的加和,而stream.map() 應該是\(\prod\).

在stream.map()中應該指定轉換條件,準確的說,應該實現一個Function()接口,這個接口將被用于stream的每一個元素,將元素按照一定的映射關系映射成新的元素。

Function接口的參數意義

使用Function接口需要導入

import java.util.function.Function;

這個接口只有一個抽象方法待用戶實現

抽象方法apply() 接受一個T類型的參數,返回一個R類型的結果

stream.map()使用示例:創建Integer流,然后映射到其原值的兩倍

ArrayList arrlist = new ArrayList();

for(int i = 1; i <= 5; i++) {

arrlist.add(i);

}

Stream st = arrlist.stream();

Stream st2 = st.map(new Function() {

@Override

public Integer apply(Integer arg0) {

return arg0 * 2;

}

});

ArrayList ans = new ArrayList();

ans = (ArrayList) st2.collect(Collectors.toList());

for(Integer i : ans) {

System.out.print(i + " ");

}

還可以用lambda表達式來實現

// 初學可以先不這么寫

ArrayList ans = (ArrayList)arrlist.stream()

.map((o1)->(2*o1))

.collect(Collectors.toList());

stream.map() 的幾種其他形式

IntStream mapToInt(ToIntFunction super T> mapper);

LongStream mapToLong(ToLongFunction super T> mapper);

DoubleStream mapToDouble(ToDoubleFunction super T> mapper);

這三者實際上是對\(Function\) 中 R的固定封裝

3.stream.flatMap()

stream.flatMap()是一個中間操作

stream.flatMap()和stream.map()都是進行映射的方法,區別在于,flatMap()處理的元素類型仍是流,flagMap用于將若干個流先拆分成若干個單個元素,再整合成一個流,即流的合并。

簡單來說,flatMap()將集合的集合降維成單個元素的集合

實例: 將數組\([[1,2,3],[4,5,6],[7,8],[9]]\)轉化為[1,2,3,4,5,6,7,8,9]

ArrayList> list_2 = new ArrayList<>();

list_2.add(new ArrayList<>(Arrays.asList(1,2,3)));

list_2.add(new ArrayList<>(Arrays.asList(4,5,6)));

list_2.add(new ArrayList<>(Arrays.asList(7,8)));

list_2.add(new ArrayList<>(Arrays.asList(9)));

ArrayList list_1 = (ArrayList) list_2.stream()

// list_2.stream() 為 "[1,2,3]" "[4,5,6]" "[7,8]" "[9]" 每個""表示流的不同元素

.flatMap((o1)->(o1).stream())

// 以 o1 = "[1,2,3]"為例,(o1)->(o1).stream() 轉化為"1","2","3"

.collect(Collectors.toList());

for(Integer i : list_1) {

System.out.print(i+" ");

}

stream.flagMap()的幾種其他形式

IntStream flatMapToInt(Function super T, ? extends IntStream> mapper);

LongStream flatMapToLong(Function super T, ? extends LongStream> mapper);

DoubleStream flatMapToDouble(Function super T, ? extends DoubleStream> mapper);

這三者實際上是對\(Function\) 中 R的固定封裝

4.stream.allMatch() ,stream.anyMatch() 和 stream.noneMatch()

stream.allMatch() 和 stream.anyMatch()均為終端操作

傳入一個Predicate函數式接口,用于指定條件

5.stream.collect()

stream.collect()為終端操作

Stream的核心在于collect,即對數據的收集。

用法一:將流轉化為Collection或Map

Collectors.toCollection() 將數據轉換成Collection,只要是Collection的實現都可以,例如ArrayList,HashSet,該方法能夠接受一個Collection對象

示例:

//List

Stream.of(1,2,3,4,5,6,7,8,9).collect(Collectors.toCollection(ArrayList::new));

//Set

Stream.of(1,2,3,4,5,6,7,8,9).collect(Collectors.toCollection(HashSet::new));

// Stream.of(1,2,3,4,5,6,7,8,9).collect(Collectors.toList());

// Stream.of(1,2,3,4,5,6,7,8,9).collect(Collectors.toSet());

// Stream.of(1,2,3,4,5,6,7,8,9).collect(Collectors.toMap(key,value));

用法二:字符串聚合規約

Collectors.joining(),拼接,有三個重載方法,底層實現是StringBuilder,通過append方法拼接到一起,并且可以自定義分隔符(這個感覺還是很有用的,很多時候需要把一個list轉成一個String,指定分隔符就可以實現了,非常方便)、前綴、后綴。

Student studentA = new Student("20190001", "小明");

Student studentB = new Student("20190002", "小紅");

Student studentC = new Student("20190003", "小丁");

//使用分隔符:201900012019000220190003

Stream.of(studentA, studentB, studentC)

.map(Student::getId)

.collect(Collectors.joining());

//使用^_^ 作為分隔符

//20190001^_^20190002^_^20190003

Stream.of(studentA, studentB, studentC)

.map(Student::getId)

.collect(Collectors.joining("^_^"));

//使用^_^ 作為分隔符

//[]作為前后綴

//[20190001^_^20190002^_^20190003]

Stream.of(studentA, studentB, studentC)

.map(Student::getId)

.collect(Collectors.joining("^_^", "[", "]"));

用法三:統計個數

Collectors.counting() 統計元素個數,這個和Stream.count() 作用都是一樣的,返回的類型一個是包裝Long,另一個是基本long,但是他們的使用場景還是有區別的,這個后面再提。

// Long 8

Stream.of(1,0,-10,9,8,100,200,-80)

.collect(Collectors.counting());

//如果僅僅只是為了統計,那就沒必要使用Collectors了,那樣更消耗資源

// long 8

Stream.of(1,0,-10,9,8,100,200,-80)

.count();

用法四:集合分組

Collectos.groupingBy()實現集合分組,返回值為一個Map

假如現在有一個實體Student

public class Student {

private String name;

private int score;

private int age;

public Student(String name,int score,int age){

this.name = name;

this.score = score;

this.age = age;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

public int getScore() {

return score;

}

public void setScore(int score) {

this.score = score;

}

public int getAge() {

return age;

}

public void setAge(int age) {

this.age = age;

}

}

現在對其按照Name分組

Map> StrListStrMap = students.stream()

.collect(Collectors.groupingBy(Student::getName));

6.stream.forEach() 和

stream.forEach() 終端操作

stream.forEach()遍歷流中的每一個元素,不一定依靠流的順序,而stream.forEachOrdered()按照流的順序遍歷。

Stream.of(1,2,3,4,5,6).forEach(System.out::println);

7.stream.max() , stream.min() , stream.count()

三個終端操作

stream.max()返回流中的最大值

stream.min()返回流中的最小值

未傳入Comparator則填null,默認用Comparable的compareTo函數比較。

stream.count()返回流中元素個數

8.stream.findAny()

返回流中任意一個元素,如果流為空,返回一個空的Optional.

List list = Arrays.asList(1, 2, 3, 4, 5, 6);

Optional any = list.stream().findAny();

總結

以上是生活随笔為你收集整理的Java0steam_Java学习 - Stream 使用的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。