一文掌握Java8新特性Stream流的概念和使用

2022-06-23 14:00:58
本篇文章給大家帶來了關於的相關知識,其中主要整理了Stream流的概念和使用的相關問題,包括了Stream流的概念、Stream流的獲取、Stream流的常用方法等等內容,下面一起來看一下,希望對大家有幫助。

推薦學習:《》

當我們說到流的時候大家就會很容易聯想到IO流,以為Stream流也是IO流,其實不然。Stream流是Java8中引入的一個全新的概念,用於解決已有集合類庫既有的一些弊端。既然要學習Stream流,我們就要暫時忘記IO流的傳統概念。我們今天就從Stream流的概念、特點、作用、使用方法等方法詳解一下Stream流,那我就一起往下看吧!

Stream流的概念

為什麼要使用Stream流?

a916621113eb4b6abbe89fa20577b99e.jpeg

Stream流的思想類似於一個生產車間的流水線。當需要對多個元素進行操作(特別是多步操作)的時候,考慮到效能及便利性,我們應該首先拼好一個「模型」步驅方案,然後再按照方案去執行它。

d5ad1f84d93347d2a729cbc9ad8bcc50.jpeg

Stream(流)是一個來自資料來源的元素佇列

元素是 特定型別的物件,形成一個佇列。lava中的Stream並不會儲存元素,而是按需計算。

資料來源 流的來源。可以是集合,陣列等。

Stream的兩個基礎的特徵:

·Pipelining:中間操作都會飯迴流物件本身。這樣多個操作可以事聯成一個管道,如同流式風格(fluentstyle)。這樣做可以對操作進行優化,比如延遲執行(laziness)和短路(short-circuiting)。

內部迭代:以前對集合遍歷都是通過iterator或者增強for的方式顯式的在集合外部進行迭代,這叫做外部迭代。Stream提供了內部迭代的方式,流可以直接呼叫遍歷方法。

當使用一個流的時候,通常包括三個基本步驟:獲取一個資料來源(source)→資料轉換一執行操作獲取想要的結果,每次轉換原有Stream物件不改變,返回一個新的Stream物件(可以有多次轉換),這就允許對其操作可以像鏈條一樣排列,變成一個管道。

Stream流的獲取

獲取流的常用方式有2種:

1.通過Collection集合獲取

2.Stream介面的靜態方法of獲取

通過Collection集合獲取

所有的Collection集合都可以通過stream預設方法獲取流

//把集合轉換為stream流

//list集合

List<String>list=new ArrayList<>();

Stream<String>stream=list.stream();

//set集合

Set<String>set=new HashSet<>();

Stream<String>stream2=set.stream();

//map集合(map集合需要間接的轉換)

Map<String, String>map=new HashMap<>();

//方法一:獲取鍵,儲存到一個set集合中

Set<String>keySet=map.keySet();

Stream<String>stream3=keySet.stream();

//方法二:獲取值,儲存到一個collection集合中

Collection<String>values=map.values();

Stream<String>stream4=values.stream();

//方法三:獲取鍵值對,,鍵與值的對映關係,entrySet()

Set<Map.Entry<String, String>>entries=map.entrySet();

Stream<Map.Entry<String, String>>stream5=entries.stream();

2.Stream介面的靜態方法of獲取

Stream介面的靜態方法of可以獲取陣列對應的流。

引數是一個可變引數,那麼我們就可以傳遞一個陣列

//把陣列轉換成Stream流

Stream<Integer>stream6=Stream.of(1,2,3,4,5);

//可變引數可以傳遞陣列

Integer[]arr={1,2,3,4,5};

Stream<Integer>stream7=Stream.of(arr);

String[]arr2={"a","bb","ccc"};

Stream<String>stream8=Stream.of(arr2);

stream流的常用方法

stream的常用方法分為兩類:

延遲方法:返回值型別仍然是Stream介面自身型別的方法,因此支援鏈式呼叫。(除了終結方法外,其餘方法均為延遲方法。)

終結方法:返回值型別不再是Stream介面自身型別的方法,因此不再支援類似StringBuilder那樣的鏈式呼叫。

cf63994dd47c44b9969ab8e44e34fec2.jpeg

以上是一些stream流的常用方法,下面我們就依次學習一下這些方法的使用。

forEach遍歷方法

該方法接受一個Consumer介面函數,會將每一個流元素交給函數進行處理。Consumer介面是一個消費性的函數式介面,可以傳遞lambda表示式,消費資料。

foeeach方法,用來遍歷流中的資料,是一個終結方法,遍歷之後就不能使用流中的其他方法。

基本使用

public class Demo03Stream_forEach {

public static void main(String[] args) {

Stream<String>stream=Stream.of("張三","李四","王五","趙六","小明","小胖");

/*stream.forEach((String name)->{

System.out.println(name);

});*/

stream.forEach(name->System.out.println(name));

}

}

filter過濾方法

用於對Stream流中的數進行過濾。filter方法的引數Predicatehi一個函數式介面,所以可以傳遞lambda表示式,對資料進行過濾。可以通過filter方法將一個轉換過濾為下一個流,如下圖:

af74ec36e72d4853a19cc830957af947.jpeg

上面這個圖把一些不也一樣的元素,用filter方法進行過濾,然後成為新的流。

基本使用

public class Demo04Stream_filter {

public static void main(String[] args) {

//建立一個Stream流

Stream<String>stream=Stream .of("張三丰","趙敏","張無忌","周芷若","張三","獅王","張大牛");

//對Stream流中的元素進行過濾。只要張的人

Stream<String>stream2=stream.filter((String name)->{return name.startsWith("張");});

//遍歷Stream流

stream2.forEach(name->System.out.println(name));

}

}

map對映方法(轉換)

如果需要將流中的元素轉換到另一個流中,可以使用map方法。該介面需要一個Funtion函數式介面引數,可以將當前流中的T型別資料型別轉換為另一種R型別的資料流,如下圖:

652b5166d5374953b7ed18d92d5e3896.jpeg

上面的圖將不同元素的資料轉換成用一種型別的元素。

基本使用

public class Demo05Stream_map {

public static void main(String[] args) {

//獲取一個String型別的Stream流

Stream<String>stream=Stream.of("1","2","3","4","5");

//使用map方法,把字串型別的整數,轉換(對映)為integer型別的整數

Stream<Integer>stream2=stream.map((String s)->{

return Integer.parseInt(s);

});

//遍歷Stream流

stream2.forEach(i->System.out.println(i));

}

}

count統計元素個數方法

用於統計Stream流中的元素個數,count方法是一個終結方法,返回值是一個Long型別的整數。所以不能再繼續呼叫Stream流中的其他方法了

基本使用

public class Demo06Stream_count {

public static void main(String[] args) {

//獲取一個Stream流

ArrayList<Integer>list=new ArrayList<Integer>();

//新增元素

list.add(1);

list.add(2);

list.add(3);

list.add(4);

list.add(5);

list.add(6);

list.add(7);

Stream<Integer>stream=list.stream();

//統計stream流中的元素個數

long count=stream.count();

//列印輸出

System.out.println(count);//7

}

}

limit擷取流元素方法

Limit方法可以對流進行擷取,只取用前n個。引數是一個long型,如果集合當前長度大於引數則進行擷取,否則不進行操作。limit方法是一個延遲方法,只是對流中的元素進行擷取,返回一個新的流,使用可以繼續呼叫stream流中的其他方法。

e023779137ac4a07bb74490a5f6ac2c5.jpeg

基本使用

public class Demo07Stream_limit {

public static void main(String[] args) {

show02();

}

private static void show02() {

//建立一個String型別的陣列

String[]arr={"喜羊羊","美羊羊","沸羊羊","懶羊羊","灰太狼","紅太狼"};

//集合獲取一個Stream流

Stream<String>stream=Stream.of(arr);

//用limit方法擷取前6個元素

Stream<String>stream2=stream.limit(3);

//遍歷Stream2流

stream2.forEach(i->System.out.println(i));

}

}

skip跳過元素方法

如果希望跳過前幾個元素,可以使用skip方法獲取一個擷取之後的新流,如果流的當前長度大於n,則跳過前n個;否則將會得到一個長度為0的流。

37268ada54e145a9a62a721fe7320728.jpeg

基本使用

public class Demo08Stream_skip {

public static void main(String[] args) {

//建立一個String型別的陣列

String[]arr={"喜羊羊","美羊羊","懶羊羊","慢羊羊","紅太狼","灰太狼","小灰灰","沸羊羊","軟綿綿","武大狼"};

//獲取Stream流

Stream<String>stream=Stream.of(arr);

//使用skip方法擷取後面的元素

Stream<String>stream2=stream.skip(5);

//遍歷stream2流

stream2.forEach(i->System.out.println(i));

}

}

concat:合併方法

用於把流組合到一塊。如果有兩個流,希望合併成為一個流,就可以使用concat方法

cf28a3d8cba044d59939bab2b67a4042.jpeg

基本使用

public class Demo09Stream_concat {

public static void main(String[] args) {

//建立一個Stream流

Stream<String>stream=Stream.of("張三丰","張翠山","趙敏","周芷若","張無忌");

//建立一個String型別的陣列

String[]arr={"喜羊羊","美羊羊","懶羊羊","慢羊羊","紅太狼","灰太狼","小灰灰","沸羊羊","軟綿綿","武大狼"};

//獲取Stream流

Stream<String>stream2=Stream.of(arr);

//使用常用方法concat方法合併流

Stream<String>stream3=Stream.concat(stream, stream2);

//遍歷Stream3流

stream3.forEach(i->System.out.println(i));

}

}

Stream流的練習

最後,我們通過下面的練習來鞏固一下上面所學的內容。

現在有兩個ArrayList集合儲存隊伍當中的多個成員姓名,

要求使用傳統的for迴圈(或增強for迴圈)依次進行以下若干操作步驟:

1.第一個隊伍只要名字為3個字的成員姓名:儲存到一個新集合中。

2.第一個隊伍篩選之後只要前3個人;儲存到一個新集合中。

3.第二個隊伍只要姓張的成員姓名;儲存到一個新集合中。

4.第二個隊伍篩選之後不要前2個人;儲存到一個新集合中。

5.將兩個隊伍合併為一個隊伍;儲存到一個新集臺中。

6.根據姓名建立Person物件:儲存到一個新集合中,

7.列印整個隊伍的Person物件資訊。

範例:

第一支隊伍:迪麗熱巴、宋遠橋、蘇星河、石破天、石中玉、老子、莊子、洪七公

第二支隊伍:古娜力扎、張無忌、趙麗穎、張三丰、尼古拉斯趙四、張天愛、張二狗

首先建立Person物件類

public class Person {

private String name;

public Person() {

super();

}

public Person(String name) {

super();

this.name = name;

}

public String getName() {

return name;

}

public void setName(String name) {

this.name = name;

}

@Override

public String toString() {

return "Person [name=" + name + "]";

}

}

然後再根據習題要求用Stream流進行過濾

1.第一個隊伍只要名字為3個字的成員姓名:儲存到一個新集合中。

2.第一個隊伍篩選之後只要前3個人;儲存到一個新集合中。

// 第一支隊伍

// 建立集合

ArrayList<String> one = new ArrayList<>();

// 新增元素

one.add("迪麗熱巴");

one.add("宋遠橋");

one.add("蘇星河");

one.add("石破天");

one.add("石中玉");

one.add("老子");

one.add("莊子");

one.add("洪七公");

//1.第一個隊伍只要名字為3個字的成員姓名:儲存到一個新集合中。

//2.第一個隊伍篩選之後只要前3個人;儲存到一個新集合中。

Stream<String>oneStream=one.stream().filter(name->name.length()==3).limit(3);

3.第二個隊伍只要姓張的成員姓名;儲存到一個新集合中。

4.第二個隊伍篩選之後不要前2個人;儲存到一個新集合中。

// 第二支隊伍

// 建立集合

ArrayList<String> tow = new ArrayList<>();

// 新增元素

tow.add("古娜力扎");

tow.add("張無忌");

tow.add("趙麗穎");

tow.add("張三丰");

tow.add("尼古拉斯趙四");

tow.add("張天愛");

tow.add("張二狗");

//3.第二個隊伍只要姓張的成員姓名;儲存到一個新集合中。

//4.第二個隊伍篩選之後不要前2個人;儲存到一個新集合中。

Stream<String>towStream=tow.stream().filter(name->name.startsWith("張")).skip(2);

5.將兩個隊伍合併為一個隊伍;儲存到一個新集臺中。

6.根據姓名建立Person物件:儲存到一個新集合中,

7.列印整個隊伍的Person物件資訊。

//5.將兩個隊伍合併為一個隊伍;儲存到一個新集臺中。

//6.根據姓名建立Person物件:儲存到一個新集合中,

//7.列印整個隊伍的Person物件資訊。

Stream.concat(oneStream,towStream).map(name->new Person(name)).forEach(p->System.out.println(p));

最後執行結果

fd3335f3e83a4c99a87fe1b235bcd308.jpeg

總結

最後,今天的內容就學到這裡啦。主要熟悉和明白Stream流的一個思想概念、會使用Stream流的獲取、和熟練掌握Stream流的一些常用方法。

c6ecc99cdfbb45cb82a75bdca69293a5.jpeg

推薦學習:《》

以上就是一文掌握Java8新特性Stream流的概念和使用的詳細內容,更多請關注TW511.COM其它相關文章!