Stream流
1.體驗(yàn)Stream流
-
案例需求
按照下面的要求完成集合的創(chuàng)建和遍歷
- 創(chuàng)建一個(gè)集合,存儲(chǔ)多個(gè)字符串元素
- 把集合中所有以"張"開(kāi)頭的元素存儲(chǔ)到一個(gè)新的集合
- 把"張"開(kāi)頭的集合中的長(zhǎng)度為3的元素存儲(chǔ)到一個(gè)新的集合
- 遍歷上一步得到的集合
-
原始方式示例代碼
public class MyStream1 { public static void main(String[] args) { //集合的批量添加 ArrayList<String> list1 = new ArrayList<>(List.of(c)); //list.add() //遍歷list1把以張開(kāi)頭的元素添加到list2中。 ArrayList<String> list2 = new ArrayList<>(); for (String s : list1) { if(s.startsWith("張")){ list2.add(s); } } //遍歷list2集合,把其中長(zhǎng)度為3的元素,再添加到list3中。 ArrayList<String> list3 = new ArrayList<>(); for (String s : list2) { if(s.length() == 3){ list3.add(s); } } for (String s : list3) { System.out.println(s); } } }
-
使用Stream流示例代碼
public class StreamDemo { public static void main(String[] args) { //集合的批量添加 ArrayList<String> list1 = new ArrayList<>(List.of("張三豐","張無(wú)忌","張翠山","王二麻子","張良","謝廣坤")); //Stream流 list1.stream().filter(s->s.startsWith("張")) .filter(s->s.length() == 3) .forEach(s-> System.out.println(s)); } }
-
Stream流的好處
- 直接閱讀代碼的字面意思即可完美展示無(wú)關(guān)邏輯方式的語(yǔ)義:獲取流、過(guò)濾姓張、過(guò)濾長(zhǎng)度為3、逐一打印
- Stream流把真正的函數(shù)式編程風(fēng)格引入到Java中
- 代碼簡(jiǎn)潔
2.Stream流的常見(jiàn)生成方式
- Stream流的思想
-
Stream流的三類(lèi)方法
- 獲取Stream流
- 創(chuàng)建一條流水線,并把數(shù)據(jù)放到流水線上準(zhǔn)備進(jìn)行操作
- 中間方法
- 流水線上的操作
- 一次操作完畢之后,還可以繼續(xù)進(jìn)行其他操作
- 終結(jié)方法
- 一個(gè)Stream流只能有一個(gè)終結(jié)方法
- 是流水線上的最后一個(gè)操作
- 獲取Stream流
-
生成Stream流的方式
-
Collection體系集合
使用默認(rèn)方法stream()生成流, default Stream stream()
-
Map體系集合
把Map轉(zhuǎn)成Set集合,間接的生成流
-
數(shù)組
通過(guò)Arrays中的靜態(tài)方法stream生成流
-
同種數(shù)據(jù)類(lèi)型的多個(gè)數(shù)據(jù)
通過(guò)Stream接口的靜態(tài)方法of(T… values)生成流
-
-
代碼演示
public class StreamDemo { public static void main(String[] args) { //Collection體系的集合可以使用默認(rèn)方法stream()生成流 List<String> list = new ArrayList<String>(); Stream<String> listStream = list.stream(); Set<String> set = new HashSet<String>(); Stream<String> setStream = set.stream(); //Map體系的集合間接的生成流 Map<String,Integer> map = new HashMap<String, Integer>(); Stream<String> keyStream = map.keySet().stream(); Stream<Integer> valueStream = map.values().stream(); Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream(); //數(shù)組可以通過(guò)Arrays中的靜態(tài)方法stream生成流 String[] strArray = {"hello","world","java"}; Stream<String> strArrayStream = Arrays.stream(strArray); //同種數(shù)據(jù)類(lèi)型的多個(gè)數(shù)據(jù)可以通過(guò)Stream接口的靜態(tài)方法of(T... values)生成流 Stream<String> strArrayStream2 = Stream.of("hello", "world", "java"); Stream<Integer> intStream = Stream.of(10, 20, 30); } }
3.Stream流中間操作方法
-
概念
中間操作的意思是,執(zhí)行完此方法之后,Stream流依然可以繼續(xù)執(zhí)行其他操作
-
常見(jiàn)方法
方法名 說(shuō)明 Stream filter(Predicate predicate) 用于對(duì)流中的數(shù)據(jù)進(jìn)行過(guò)濾 Stream limit(long maxSize) 返回此流中的元素組成的流,截取前指定參數(shù)個(gè)數(shù)的數(shù)據(jù) Stream skip(long n) 跳過(guò)指定參數(shù)個(gè)數(shù)的數(shù)據(jù),返回由該流的剩余元素組成的流 static Stream concat(Stream a, Stream b) 合并a和b兩個(gè)流為一個(gè)流 Stream distinct() 返回由該流的不同元素(根據(jù)Object.equals(Object) )組成的流 -
filter代碼演示
public class MyStream3 { public static void main(String[] args) { // Stream<T> filter(Predicate predicate):過(guò)濾 // Predicate接口中的方法 boolean test(T t):對(duì)給定的參數(shù)進(jìn)行判斷,返回一個(gè)布爾值 ArrayList<String> list = new ArrayList<>(); list.add("張三豐"); list.add("張無(wú)忌"); list.add("張翠山"); list.add("王二麻子"); list.add("張良"); list.add("謝廣坤"); //filter方法獲取流中的 每一個(gè)數(shù)據(jù). //而test方法中的s,就依次表示流中的每一個(gè)數(shù)據(jù). //我們只要在test方法中對(duì)s進(jìn)行判斷就可以了. //如果判斷的結(jié)果為true,則當(dāng)前的數(shù)據(jù)留下 //如果判斷的結(jié)果為false,則當(dāng)前數(shù)據(jù)就不要. // list.stream().filter( // new Predicate<String>() { // @Override // public boolean test(String s) { // boolean result = s.startsWith("張"); // return result; // } // } // ).forEach(s-> System.out.println(s)); //因?yàn)镻redicate接口中只有一個(gè)抽象方法test //所以我們可以使用lambda表達(dá)式來(lái)簡(jiǎn)化 // list.stream().filter( // (String s)->{ // boolean result = s.startsWith("張"); // return result; // } // ).forEach(s-> System.out.println(s)); list.stream().filter(s ->s.startsWith("張")).forEach(s-> System.out.println(s)); } }
-
limit&skip代碼演示
public class StreamDemo02 { public static void main(String[] args) { //創(chuàng)建一個(gè)集合,存儲(chǔ)多個(gè)字符串元素 ArrayList<String> list = new ArrayList<String>(); list.add("林青霞"); list.add("張曼玉"); list.add("王祖賢"); list.add("柳巖"); list.add("張敏"); list.add("張無(wú)忌"); //需求1:取前3個(gè)數(shù)據(jù)在控制臺(tái)輸出 list.stream().limit(3).forEach(s-> System.out.println(s)); System.out.println("--------"); //需求2:跳過(guò)3個(gè)元素,把剩下的元素在控制臺(tái)輸出 list.stream().skip(3).forEach(s-> System.out.println(s)); System.out.println("--------"); //需求3:跳過(guò)2個(gè)元素,把剩下的元素中前2個(gè)在控制臺(tái)輸出 list.stream().skip(2).limit(2).forEach(s-> System.out.println(s)); } }
-
concat&distinct代碼演示
public class StreamDemo03 { public static void main(String[] args) { //創(chuàng)建一個(gè)集合,存儲(chǔ)多個(gè)字符串元素 ArrayList<String> list = new ArrayList<String>(); list.add("林青霞"); list.add("張曼玉"); list.add("王祖賢"); list.add("柳巖"); list.add("張敏"); list.add("張無(wú)忌"); //需求1:取前4個(gè)數(shù)據(jù)組成一個(gè)流 Stream<String> s1 = list.stream().limit(4); //需求2:跳過(guò)2個(gè)數(shù)據(jù)組成一個(gè)流 Stream<String> s2 = list.stream().skip(2); //需求3:合并需求1和需求2得到的流,并把結(jié)果在控制臺(tái)輸出 // Stream.concat(s1,s2).forEach(s-> System.out.println(s)); //需求4:合并需求1和需求2得到的流,并把結(jié)果在控制臺(tái)輸出,要求字符串元素不能重復(fù) Stream.concat(s1,s2).distinct().forEach(s-> System.out.println(s)); } }
4.Stream流終結(jié)操作方法
-
概念
終結(jié)操作的意思是,執(zhí)行完此方法之后,Stream流將不能再執(zhí)行其他操作
-
常見(jiàn)方法
方法名 說(shuō)明 void forEach(Consumer action) 對(duì)此流的每個(gè)元素執(zhí)行操作 long count() 返回此流中的元素?cái)?shù) -
代碼演示
public class MyStream5 { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("張三豐"); list.add("張無(wú)忌"); list.add("張翠山"); list.add("王二麻子"); list.add("張良"); list.add("謝廣坤"); //method1(list); // long count():返回此流中的元素?cái)?shù) long count = list.stream().count(); System.out.println(count); } private static void method1(ArrayList<String> list) { // void forEach(Consumer action):對(duì)此流的每個(gè)元素執(zhí)行操作 // Consumer接口中的方法void accept(T t):對(duì)給定的參數(shù)執(zhí)行此操作 //在forEach方法的底層,會(huì)循環(huán)獲取到流中的每一個(gè)數(shù)據(jù). //并循環(huán)調(diào)用accept方法,并把每一個(gè)數(shù)據(jù)傳遞給accept方法 //s就依次表示了流中的每一個(gè)數(shù)據(jù). //所以,我們只要在accept方法中,寫(xiě)上處理的業(yè)務(wù)邏輯就可以了. list.stream().forEach( new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); } } ); System.out.println("===================="); //lambda表達(dá)式的簡(jiǎn)化格式 //是因?yàn)镃onsumer接口中,只有一個(gè)accept方法 list.stream().forEach( (String s)->{ System.out.println(s); } ); System.out.println("===================="); //lambda表達(dá)式還是可以進(jìn)一步簡(jiǎn)化的. list.stream().forEach(s->System.out.println(s)); } }
5.Stream流的收集操作
-
概念
對(duì)數(shù)據(jù)使用Stream流的方式操作完畢后,可以把流中的數(shù)據(jù)收集到集合中
-
常用方法
方法名 說(shuō)明 R collect(Collector collector) 把結(jié)果收集到集合中 -
工具類(lèi)Collectors提供了具體的收集方式
方法名 說(shuō)明 public static Collector toList() 把元素收集到List集合中 public static Collector toSet() 把元素收集到Set集合中 public static Collector toMap(Function keyMapper,Function valueMapper) 把元素收集到Map集合中 -
代碼演示
// toList和toSet方法演示 public class MyStream7 { public static void main(String[] args) { ArrayList<Integer> list1 = new ArrayList<>(); for (int i = 1; i <= 10; i++) { list1.add(i); } list1.add(10); list1.add(10); list1.add(10); list1.add(10); list1.add(10); //filter負(fù)責(zé)過(guò)濾數(shù)據(jù)的. //collect負(fù)責(zé)收集數(shù)據(jù). //獲取流中剩余的數(shù)據(jù),但是他不負(fù)責(zé)創(chuàng)建容器,也不負(fù)責(zé)把數(shù)據(jù)添加到容器中. //Collectors.toList() : 在底層會(huì)創(chuàng)建一個(gè)List集合.并把所有的數(shù)據(jù)添加到List集合中. List<Integer> list = list1.stream().filter(number -> number % 2 == 0) .collect(Collectors.toList()); System.out.println(list); Set<Integer> set = list1.stream().filter(number -> number % 2 == 0) .collect(Collectors.toSet()); System.out.println(set); } } /** Stream流的收集方法 toMap方法演示 創(chuàng)建一個(gè)ArrayList集合,并添加以下字符串。字符串中前面是姓名,后面是年齡 "zhangsan,23" "lisi,24" "wangwu,25" 保留年齡大于等于24歲的人,并將結(jié)果收集到Map集合中,姓名為鍵,年齡為值 */ public class MyStream8 { public static void main(String[] args) { ArrayList<String> list = new ArrayList<>(); list.add("zhangsan,23"); list.add("lisi,24"); list.add("wangwu,25"); Map<String, Integer> map = list.stream().filter( s -> { String[] split = s.split(","); int age = Integer.parseInt(split[1]); return age >= 24; } // collect方法只能獲取到流中剩余的每一個(gè)數(shù)據(jù). //在底層不能創(chuàng)建容器,也不能把數(shù)據(jù)添加到容器當(dāng)中 //Collectors.toMap 創(chuàng)建一個(gè)map集合并將數(shù)據(jù)添加到集合當(dāng)中 // s 依次表示流中的每一個(gè)數(shù)據(jù) //第一個(gè)lambda表達(dá)式就是如何獲取到Map中的鍵 //第二個(gè)lambda表達(dá)式就是如何獲取Map中的值 ).collect(Collectors.toMap( s -> s.split(",")[0], s -> Integer.parseInt(s.split(",")[1]) )); System.out.println(map); } }
6.Stream流綜合練習(xí)
-
案例需求
現(xiàn)在有兩個(gè)ArrayList集合,分別存儲(chǔ)6名男演員名稱(chēng)和6名女演員名稱(chēng),要求完成如下的操作
- 男演員只要名字為3個(gè)字的前三人
- 女演員只要姓林的,并且不要第一個(gè)
- 把過(guò)濾后的男演員姓名和女演員姓名合并到一起
- 把上一步操作后的元素作為構(gòu)造方法的參數(shù)創(chuàng)建演員對(duì)象,遍歷數(shù)據(jù)
演員類(lèi)Actor已經(jīng)提供,里面有一個(gè)成員變量,一個(gè)帶參構(gòu)造方法,以及成員變量對(duì)應(yīng)的get/set方法
-
代碼實(shí)現(xiàn)
演員類(lèi)
public class Actor { private String name; public Actor(String name) { this.name = name; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
測(cè)試類(lèi)文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-716060.html
public class StreamTest { public static void main(String[] args) { //創(chuàng)建集合 ArrayList<String> manList = new ArrayList<String>(); manList.add("周潤(rùn)發(fā)"); manList.add("成龍"); manList.add("劉德華"); manList.add("吳京"); manList.add("周星馳"); manList.add("李連杰"); ArrayList<String> womanList = new ArrayList<String>(); womanList.add("林心如"); womanList.add("張曼玉"); womanList.add("林青霞"); womanList.add("柳巖"); womanList.add("林志玲"); womanList.add("王祖賢"); //男演員只要名字為3個(gè)字的前三人 Stream<String> manStream = manList.stream().filter(s -> s.length() == 3).limit(3); //女演員只要姓林的,并且不要第一個(gè) Stream<String> womanStream = womanList.stream().filter(s -> s.startsWith("林")).skip(1); //把過(guò)濾后的男演員姓名和女演員姓名合并到一起 Stream<String> stream = Stream.concat(manStream, womanStream); // 將流中的數(shù)據(jù)封裝成Actor對(duì)象之后打印 stream.forEach(name -> { Actor actor = new Actor(name); System.out.println(actor); }); } }
后記
????????美好的一天,到此結(jié)束,下次繼續(xù)努力!欲知后續(xù),請(qǐng)看下回分解,寫(xiě)作不易,感謝大家的支持?。???????文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-716060.html
到了這里,關(guān)于從零開(kāi)始學(xué)習(xí) Java:簡(jiǎn)單易懂的入門(mén)指南之Stream流(二十七)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!