【Java】Stream流和方法引用
1 Stream流
1.1 Stream流優化過濾集合
傳統方式
Stream流
 JDK1.8后出現,關注做什么,而不是怎么做
1.2 流式思想概述
拼接流式模型:建立一個生產線,按照生產線來生產商品。
當使用一個流的時候,通常包括三個基本步驟:
每次轉換原有 Stream 對象不改變,返回一個新的 Stream 對象(可以有多次轉換),這就允許對其操作可以像鏈條一樣排列,變成一個管道。
1.3 獲取流
java.util.stream.Stream<T> 是Java 8新加入的最常用的流接口。
 (這并不是一個函數式接口。)
獲取一個流有以下幾種常用的方式:
流的特點:Stream流屬于管道流,只能使用一次,第一個流使用完畢就會關閉,這個流就不可以再調用其他方法了。
1.4 常用方法
流模型的操作很豐富,這里介紹一些常用的API。這些方法可以被分成兩種:
forEach方法:forEach的參數是Consumer
//forEach的參數的Consumer//Consumer接口是一個消費型的函數式接口,可以傳遞lambda表達式消費數據public static void main(String[] args) {Stream<String> stream = Stream.of("張三", "李四", "王五");stream.forEach(name-> System.out.println(name));}filter方法:filter的參數是Predicate,用于將一個流轉換成另一個子集流
//forEach的參數是該接口接收一個Predicate//函數式接口參數(可以是一個Lambda或方法引用)作為篩選條件。//test方法將會產生一個boolean值結果,代表指定的條件是否滿足。//如果結果為true,那么Stream流的filter 方法//將會留用元素;如果結果為false,那么filter 方法將會舍棄元素。public static void main(String[] args) {Stream<String> stream = Stream.of("張三", "張四","李四", "王五");Stream<String> stream1 = stream.filter((name) -> {return name.startsWith("張");});stream1.forEach(name-> System.out.println(name));}map方法:
 如果需要將流中的元素映射到另一個流中,可以用map。可以將T類型的流轉換為R類型的流。java.util.stream.Function 函數式接口,其中唯一的抽象方法為:apply。這可以將一種T類型轉換成為R類型,而這種轉換的動作,就稱為“映射”。
將integer類型轉換為string類型
public static void main(String[] args) {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);Stream<String> stream2 = stream.map((Integer i) -> {return String.valueOf(i);});stream2.forEach((s)-> System.out.println(s));}count方法
 用于統計Stream流中的元素個數。正如舊集合Collection 當中的size 方法一樣,流提供count 方法來數一數其中的元素個數。count方法返回值是long類型的整數,是終結方法,,之后不能再繼續調用其他方法。
limit方法:可以對流進行截取。參數是long類型的整數。屬于延遲方法,可以繼續調用其他方法。如果集合當前長度大于參數則進行截取;否則不進行操作,即還是原流。
public static void main(String[] args) {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);stream.limit(3).forEach((num)-> System.out.println(num));}skip方法:可以跳過前幾個元素,獲取一個截取之后的新流。參數超過元素個數,返回空流。
public static void main(String[] args) {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);stream.skip(3).forEach((num)-> System.out.println(num));}concat方法:組合兩個流為一個流。concat是靜態方法,通過接口名調用。
public static void main(String[] args) {Stream<Integer> stream1 = Stream.of(1, 2, 3, 4, 5);Stream<String> stream2 = Stream.of("a","b","c","d");Stream.concat(stream1,stream2).forEach((s)-> System.out.println(s));}1.5 練習-集合元素處理
現在有兩個ArrayList 集合存儲隊伍當中的多個成員姓名,要求使用傳統的for循環(或增強for循環)依次進行以下若干操作步驟:
 第一個隊伍只要名字為3個字的成員姓名;
 第一個隊伍篩選之后只要前3個人;
 第二個隊伍只要姓張的成員姓名;
 第二個隊伍篩選之后不要前2個人;
 將兩個隊伍合并為一個隊伍;
 根據姓名創建Person 對象;
 打印整個隊伍的Person對象信息。
Stream方式
public static void main(String[] args) {ArrayList<Person> list1 = new ArrayList<>();list1.add(new Person("李白"));list1.add(new Person("杜甫"));list1.add(new Person("李清照"));list1.add(new Person("王勃"));list1.add(new Person("劉禹錫"));list1.add(new Person("辛棄疾"));list1.add(new Person("龔自珍"));ArrayList<Person> list2 = new ArrayList<>();list2.add(new Person("李四"));list2.add(new Person("王五"));list2.add(new Person("張一"));list2.add(new Person("張二"));list2.add(new Person("張三"));Stream<Person> newlist1 = list1.stream().filter((person) -> {return person.getName().length() == 3;}).limit(3);Stream<Person> newlist2 = list2.stream().filter((person) -> {return person.getName().startsWith("張");}).skip(2);Stream.concat(newlist1, newlist2).forEach((person)-> System.out.println(person));}2 方法引用
2.1 應用:簡化lambda
雙冒號:: 為引用運算符,而它所在的表達式被稱為方法引用。如果Lambda要表達的函數方案已經存在于某個方法的實現中,那么則可以通過雙冒號來引用該方法作為Lambda的替代者。
例如上方代碼中的最后一句可以等價為:
Stream.concat(newlist1, newlist2).forEach((person)-> System.out.println(person)); Stream.concat(newlist1, newlist2).forEach(System.out::println);2.2 通過對象名引用成員方法
自定義一個接口
public interface Printable {void print(String s); }自定義一個類及其成員方法
public class MethodRerObject {public void printUpperCaseString(String str){System.out.println(str.toUpperCase());} }測試
public class Test {//通過對象名引用成員方法//前提:對象名存在,成員方法存在public static void printString(Printable p){p.print("Hello");}public static void main(String[] args) {//用lambdaprintString((s)->{MethodRerObject obj = new MethodRerObject();obj.printUpperCaseString(s);});//方法引用優化//對象和成員方法都存在MethodRerObject obj = new MethodRerObject();printString(obj::printUpperCaseString);} }2.3 通過類名引用靜態成員方法
定義一個函數式接口
@FunctionalInterface public interface Calcable {int calAbs(int num); }定義一個方法傳遞接口和整數
public class Test {public static int method(int number, Calcable c){return c.calAbs(number);}public static void main(String[] args) {//調用method方法int result = method(-10, (num) -> Math.abs(num));System.out.println(result);//使用方法引用優化 Math存在 abs的靜態方法也存在int result2 = method(-10, Math::abs);System.out.println(result2);} }2.4 通過super引用父類成員方法
定義函數式接口
public interface Greatable {void great(); }定義父類
public class Human {public void sayHello(){System.out.println("Hello, i am human");} }定義子類
public class Man extends Human{@Overridepublic void sayHello(){System.out.println("Hello, i am man");}public void great(Greatable g){g.great();}public void show(){great(()->{Human h = new Human();h.sayHello();});//通過父類調用great(()->{super.sayHello();});//通過父類引用great(super::sayHello);}public static void main(String[] args) {new Man().show();} }2.5 通過this引用本類成員方法
public interface Richable {void buy(); } public class Husband {public void buyHouse(){System.out.println("買房子");}public void marry(Richable r){r.buy();}public void soHappy(){//this和buyHouse都是以及存在的 可以直接用this來引用本類方法//marry(()->this.buyHouse());marry(this::buyHouse);}public static void main(String[] args) {new Husband().soHappy();} }2.6 類的構造器引用
自定義一個Person類,自定義一個創建Person的接口
public interface PersonBuilder {Person buildPerson(String name); } public class Test {public static void printName(String name, PersonBuilder pb){Person person = pb.buildPerson(name);System.out.println(person.getName());}public static void main(String[] args) {//調用method方法printName("張三",(name)->new Person(name));//使用方法引用優化 Person的構造方法已知 創建對象new已知printName("李四", Person::new);} }2.7 數組的構造器引用
@FunctionalInterface public interface ArrayBuilder {int[] buiderArray(int length); } public class Test {public static int[] createArray(int len, ArrayBuilder ab){return ab.buiderArray(len);}public static void main(String[] args) {//調用method方法int[] array = createArray(10, (len) ->new int[len]);System.out.println(array.length);//使用方法引用優化lambda 已知創建的是int類型的數組 數組的長度已知int[] array1 = createArray(10, int[]::new);System.out.println(array1.length);} }總結
以上是生活随笔為你收集整理的【Java】Stream流和方法引用的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: Githug第42关rebase_ont
 - 下一篇: 浅谈事理图谱认知:系统体系+领域收敛+人