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

歡迎訪問 生活随笔!

生活随笔

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

java

【Java】Stream流和方法引用

發布時間:2024/7/5 java 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【Java】Stream流和方法引用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1 Stream流

1.1 Stream流優化過濾集合

傳統方式

  • 用一個循環過濾姓張的人
  • 用一個循環過濾名字長度大于2的人
  • public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("張三");list.add("李四");list.add("張三三");list.add("張四四");list.add("李四四");ArrayList<String> newlist = new ArrayList<>();for(String s: list){if(s.startsWith("張")&&s.length()>2){listWithZhang.add(s);}}for(String s: newlist){System.out.println(s);}}

    Stream流
    JDK1.8后出現,關注做什么,而不是怎么做

    public static void main(String[] args) {ArrayList<String> list = new ArrayList<>();list.add("張三");list.add("李四");list.add("張三三");list.add("張四四");list.add("李四四");list.stream().filter((name)->name.startsWith("張")).filter((name)->name.length()>2).forEach((name)->{System.out.println(name);});}

    1.2 流式思想概述

    拼接流式模型:建立一個生產線,按照生產線來生產商品。

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

  • 獲取一個數據源(source)→
  • 數據轉換→
  • 執行操作獲取想要的結果.
  • 每次轉換原有 Stream 對象不改變,返回一個新的 Stream 對象(可以有多次轉換),這就允許對其操作可以像鏈條一樣排列,變成一個管道。

    1.3 獲取流

    java.util.stream.Stream<T> 是Java 8新加入的最常用的流接口。
    (這并不是一個函數式接口。)

    獲取一個流有以下幾種常用的方式:

  • 所有的Collection集合都可以通過 stream 默認方法獲取流;
  • Stream 接口的靜態方法 of 可以獲取數組對應的流。
  • public static void main(String[] args) {//集合調用stream方法可以獲得ArrayList<String> list = new ArrayList<>();Stream<String> stream1 = list.stream();//數組可以用Stream.of獲得Stream<Integer> stream6 = Stream.of(1, 2, 3, 4, 5, 6);Integer[] arr = {1, 2, 3, 5};Stream<Integer> steam7 = Stream.of(arr);}

    流的特點:Stream流屬于管道流,只能使用一次,第一個流使用完畢就會關閉,這個流就不可以再調用其他方法了。

    1.4 常用方法

    流模型的操作很豐富,這里介紹一些常用的API。這些方法可以被分成兩種:

  • 延遲方法:返回值類型仍然是Stream 接口自身類型的方法,因此支持鏈式調用。(除了終結方法外,其余方法均為延遲方法。)
  • 終結方法:返回值類型不再是Stream 接口自身類型的方法,因此不再支持類似StringBuilder 那樣的鏈式調用。(例如:count 和forEach方法)。
  • 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類型的整數,是終結方法,,之后不能再繼續調用其他方法。

    public static void main(String[] args) {Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5);long count = stream.count();System.out.println(count);}

    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流和方法引用的全部內容,希望文章能夠幫你解決所遇到的問題。

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