Stream流

  • 說到Stream便容易想到I/O Stream实辑,而實(shí)際上零抬,誰規(guī)定“流”就一定是“IO流”呢?在Java 8中沛膳,得益于Lambda所帶來的函數(shù)式編程
  • 引入了一個(gè)全新的Stream概念扁远,用于解決已有集合+數(shù)組既有的弊端俊鱼。

/*
    使用Stream流的方式,遍歷集合,對集合中的數(shù)據(jù)進(jìn)行過濾
    Stream流是JDK1.8之后出現(xiàn)的
    關(guān)注的是做什么,而不是怎么做
 */
public class Demo02Stream {
    public static void main(String[] args) {
        //創(chuàng)建一個(gè)List集合,存儲姓名
        List<String> list = new ArrayList<>();
        list.add("張無忌");
        list.add("周芷若");
        list.add("趙敏");
        list.add("張強(qiáng)");
        list.add("張三豐");

        //對list集合中的元素進(jìn)行過濾,只要以張開頭的元素,存儲到一個(gè)新的集合中
        //對listA集合進(jìn)行過濾,只要姓名長度為3的人,存儲到一個(gè)新集合中
        //遍歷listB集合
        // 獲取流、過濾姓張畅买、過濾長度為3并闲、逐一打印
        list.stream()
                .filter(name->name.startsWith("張"))
            .filter(name->name.length()==3)
            .forEach(name-> System.out.println(name));
  }
}
  • 使用一個(gè)流的時(shí)候,通常包括三個(gè)基本步驟:獲取一個(gè)數(shù)據(jù)源(source)→ 數(shù)據(jù)轉(zhuǎn)換→執(zhí)行操作獲取想要的結(jié)果谷羞,每次轉(zhuǎn)換原有 Stream 對象不改變帝火,返回一個(gè)新的 Stream 對象(可以有多次轉(zhuǎn)換)
    獲取流
  • java.util.stream.Stream<T> 是Java 8新加入的最常用的流接口。(這并不是一個(gè)函數(shù)式接口湃缎。)
  • 獲取一個(gè)流非常簡單犀填,有以下幾種常用的方式:
  1. 所有的 Collection 集合都可以通過 stream 默認(rèn)方法獲取流;
  2. Stream 接口的靜態(tài)方法 of 可以獲取數(shù)組對應(yīng)的流嗓违。
/*
    java.util.stream.Stream<T>是Java 8新加入的最常用的流接口九巡。(這并不是一個(gè)函數(shù)式接口。)
    獲取一個(gè)流非常簡單蹂季,有以下幾種常用的方式:
        - 所有的Collection集合都可以通過stream默認(rèn)方法獲取流冕广;
            default Stream<E> stream?()
        - Stream接口的靜態(tài)方法of可以獲取數(shù)組對應(yīng)的流。
            static <T> Stream<T> of?(T... values)
            參數(shù)是一個(gè)可變參數(shù),那么我們就可以傳遞一個(gè)數(shù)組
 */
public class Demo01GetStream {
    public static void main(String[] args) {
        //把集合轉(zhuǎn)換為Stream流
        List<String> list = new ArrayList<>();
        Stream<String> stream1 = list.stream();

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

        Map<String,String> map = new HashMap<>();
        //獲取鍵,存儲到一個(gè)Set集合中
        Set<String> keySet = map.keySet();
        Stream<String> stream3 = keySet.stream();

        //獲取值,存儲到一個(gè)Collection集合中
        Collection<String> values = map.values();
        Stream<String> stream4 = values.stream();

        //獲取鍵值對(鍵與值的映射關(guān)系 entrySet)
        Set<Map.Entry<String, String>> entries = map.entrySet();
        Stream<Map.Entry<String, String>> stream5 = entries.stream();

        //把數(shù)組轉(zhuǎn)換為Stream流
        Stream<Integer> stream6 = Stream.of(1, 2, 3, 4, 5);
        //可變參數(shù)可以傳遞數(shù)組
        Integer[] arr = {1,2,3,4,5};
        Stream<Integer> stream7 = Stream.of(arr);
        String[] arr2 = {"a","bb","ccc"};
        Stream<String> stream8 = Stream.of(arr2);
    }
}

forEach

/*
    Stream流中的常用方法_forEach
    void forEach(Consumer<? super T> action);
    該方法接收一個(gè)Consumer接口函數(shù)偿洁,會將每一個(gè)流元素交給該函數(shù)進(jìn)行處理撒汉。
    Consumer接口是一個(gè)消費(fèi)型的函數(shù)式接口,可以傳遞Lambda表達(dá)式,消費(fèi)數(shù)據(jù)

    簡單記:
        forEach方法,用來遍歷流中的數(shù)據(jù)
        是一個(gè)終結(jié)方法,遍歷之后就不能繼續(xù)調(diào)用Stream流中的其他方法
 */
public class Demo02Stream_forEach {
    public static void main(String[] args) {
        //獲取一個(gè)Stream流
        Stream<String> stream = Stream.of("張三", "李四", "王五", "趙六", "田七");
        //使用Stream流中的方法forEach對Stream流中的數(shù)據(jù)進(jìn)行遍歷
        /*stream.forEach((String name)->{
            System.out.println(name);
        });*/

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

filter

/*
    Stream流中的常用方法_filter:用于對Stream流中的數(shù)據(jù)進(jìn)行過濾
    Stream<T> filter(Predicate<? super T> predicate);
    filter方法的參數(shù)Predicate是一個(gè)函數(shù)式接口,所以可以傳遞Lambda表達(dá)式,對數(shù)據(jù)進(jìn)行過濾
    Predicate中的抽象方法:
        boolean test(T t);
 */
public class Demo03Stream_filter {
    public static void main(String[] args) {
        //創(chuàng)建一個(gè)Stream流
        Stream<String> stream = Stream.of("張三豐", "張翠山", "趙敏", "周芷若", "張無忌");
        //對Stream流中的元素進(jìn)行過濾,只要姓張的人
        Stream<String> stream2 = stream.filter((String name)->{return name.startsWith("張");});
        //遍歷stream2流
        stream2.forEach(name-> System.out.println(name));

        /*
            Stream流屬于管道流,只能被消費(fèi)(使用)一次
            第一個(gè)Stream流調(diào)用完畢方法,數(shù)據(jù)就會流轉(zhuǎn)到下一個(gè)Stream上
            而這時(shí)第一個(gè)Stream流已經(jīng)使用完畢,就會關(guān)閉了
            所以第一個(gè)Stream流就不能再調(diào)用方法了
            IllegalStateException: stream has already been operated upon or closed
         */
        //遍歷stream流
        stream.forEach(name-> System.out.println(name));
    }
}

map

/*
    Stream流中的常用方法_map:用于類型轉(zhuǎn)換
    如果需要將流中的元素映射到另一個(gè)流中,可以使用map方法.
    <R> Stream<R> map(Function<? super T, ? extends R> mapper);
    該接口需要一個(gè)Function函數(shù)式接口參數(shù)涕滋,可以將當(dāng)前流中的T類型數(shù)據(jù)轉(zhuǎn)換為另一種R類型的流神凑。
    Function中的抽象方法:
        R apply(T t);
 */
public class Demo04Stream_map {
    public static void main(String[] args) {
        //獲取一個(gè)String類型的Stream流
        Stream<String> stream = Stream.of("1", "2", "3", "4");
        //使用map方法,把字符串類型的整數(shù),轉(zhuǎn)換(映射)為Integer類型的整數(shù)
        Stream<Integer> stream2 = stream.map((String s)->{
            return Integer.parseInt(s);
        });
        //遍歷Stream2流
        stream2.forEach(i-> System.out.println(i));
    }
}

count

/*
    Stream流中的常用方法_count:用于統(tǒng)計(jì)Stream流中元素的個(gè)數(shù)
    long count();
    count方法是一個(gè)終結(jié)方法,返回值是一個(gè)long類型的整數(shù)
    所以不能再繼續(xù)調(diào)用Stream流中的其他方法了
 */
public class Demo05Stream_count {
    public static void main(String[] args) {
        //獲取一個(gè)Stream流
        ArrayList<Integer> list = new ArrayList<>();
        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();
        long count = stream.count();
        System.out.println(count);//7
    }
}

limit

/*
    Stream流中的常用方法_limit:用于截取流中的元素
    limit方法可以對流進(jìn)行截取,只取用前n個(gè)何吝。方法簽名:
    Stream<T> limit(long maxSize);
        參數(shù)是一個(gè)long型,如果集合當(dāng)前長度大于參數(shù)則進(jìn)行截染槲ā爱榕;否則不進(jìn)行操作
    limit方法是一個(gè)延遲方法,只是對流中的元素進(jìn)行截取,返回的是一個(gè)新的流,所以可以繼續(xù)調(diào)用Stream流中的其他方法
 */
public class Demo06Stream_limit {
    public static void main(String[] args) {
        //獲取一個(gè)Stream流
        String[] arr = {"美羊羊","喜洋洋","懶洋洋","灰太狼","紅太狼"};
        Stream<String> stream = Stream.of(arr);
        //使用limit對Stream流中的元素進(jìn)行截取,只要前3個(gè)元素
        Stream<String> stream2 = stream.limit(3);
        //遍歷stream2流
        stream2.forEach(name-> System.out.println(name));
    }
}

skip

/*
    Stream流中的常用方法_skip:用于跳過元素
    如果希望跳過前幾個(gè)元素,可以使用skip方法獲取一個(gè)截取之后的新流:
    Stream<T> skip(long n);
        如果流的當(dāng)前長度大于n坡慌,則跳過前n個(gè)黔酥;否則將會得到一個(gè)長度為0的空流。
 */
public class Demo07Stream_skip {
    public static void main(String[] args) {
        //獲取一個(gè)Stream流
        String[] arr = {"美羊羊","喜洋洋","懶洋洋","灰太狼","紅太狼"};
        Stream<String> stream = Stream.of(arr);
        //使用skip方法跳過前3個(gè)元素
        Stream<String> stream2 = stream.skip(3);
        //遍歷stream2流
        stream2.forEach(name-> System.out.println(name));
    }
}

concat

/*
    Stream流中的常用方法_concat:用于把流組合到一起
    如果有兩個(gè)流,希望合并成為一個(gè)流跪者,那么可以使用Stream接口的靜態(tài)方法concat
    static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b)
 */
public class Demo08Stream_concat {
    public static void main(String[] args) {
        //創(chuàng)建一個(gè)Stream流
        Stream<String> stream1 = Stream.of("張三豐", "張翠山", "趙敏", "周芷若", "張無忌");
        //獲取一個(gè)Stream流
        String[] arr = {"美羊羊","喜洋洋","懶洋洋","灰太狼","紅太狼"};
        Stream<String> stream2 = Stream.of(arr);
        //把以上兩個(gè)流組合為一個(gè)流
        Stream<String> concat = Stream.concat(stream1, stream2);
        //遍歷concat流
        concat.forEach(name-> System.out.println(name));
    }
}

toMap

    /**
     * 3棵帽、list轉(zhuǎn)為Map
     */
    @Test
    public void lambatoMap(){
        List<User> list = new ArrayList<>();
        User user1 = new User("張三",15,"男");
        User user2 = new User("李四",22,"男");
        User user3 = new User("張三",22,"男");
        User user4 = new User("趙六",15,"男");
        User user5 = new User("李世民",28,"男");
        User user6 = new User("楊貴妃",18,"女");
        User user7 = new User("李四",15,"女");
        list.add(user1);
        list.add(user2);
        list.add(user3);
        list.add(user4);
        list.add(user5);
        list.add(user6);
        list.add(user7);
        
       //age為key,list轉(zhuǎn)為Map,若key重復(fù)則渣玲,看選擇第一個(gè)對象
        Map<Integer, User> collect = list.stream().collect(Collectors.toMap(User::getAge, a -> a,(k1, k2)->k1));
        System.out.println(collect);
    }

sum

    /**
     * 5逗概、求和:將集合中的數(shù)據(jù)按照某個(gè)屬性求和
     */
    @Test
    public void lambamapToInt(){
        List<User> list = new ArrayList<>();
        User user1 = new User("張三",15,"男");
        User user2 = new User("李四",22,"男");
        User user3 = new User("張三",22,"男");
        User user4 = new User("趙六",15,"男");
        User user5 = new User("李世民",28,"男");
        User user6 = new User("楊貴妃",18,"女");
        User user7 = new User("李四",15,"女");
        list.add(user1);
        list.add(user2);
        list.add(user3);
        list.add(user4);
        list.add(user5);
        list.add(user6);
        list.add(user7);
        
        int totalAge = list.stream().mapToInt(User::getAge).sum();
        System.out.println("和:" + totalAge);
    }

groupingBy

    /**
     * 2、將List分組:List里面的對象元素忘衍,以某個(gè)屬性來分組
     */
    @Test
    public void lambagroupBy(){
        List<User> list = new ArrayList<>();
        User user1 = new User("張三",15,"男");
        User user2 = new User("李四",22,"男");
        User user3 = new User("張三",22,"男");
        User user4 = new User("趙六",15,"男");
        User user5 = new User("李世民",28,"男");
        User user6 = new User("楊貴妃",18,"女");
        User user7 = new User("李四",15,"女");
        list.add(user1);
        list.add(user2);
        list.add(user3);
        list.add(user4);
        list.add(user5);
        list.add(user6);
        list.add(user7);
        
        //根據(jù)name來將userList分組
        Map<String, List<User>> groupBy = list.stream().collect(Collectors.groupingBy(User::getName));
        Map<String, Map<Integer, List<User>>> groupBy = list.stream().collect(Collectors.groupingBy(User::getName,User::getAge));
        System.out.println(groupBy);
    }
package com.lamba;

public class User {
    private String name;
    private int age;
    private String sex;
    
    public User(String name, int age, String sex) {
        super();
        this.name = name;
        this.age = age;
        this.sex = sex;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getSex() {
        return sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    @Override
    public String toString() {
        return "User [name=" + name + ", age=" + age + ", sex=" + sex + "]";
    }
    
}


更多應(yīng)用請參考:https://blog.csdn.net/chaoer89/article/details/52389458/

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末逾苫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子枚钓,更是在濱河造成了極大的恐慌铅搓,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件搀捷,死亡現(xiàn)場離奇詭異星掰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)嫩舟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進(jìn)店門氢烘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人至壤,你說我怎么就攤上這事威始。” “怎么了像街?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵黎棠,是天一觀的道長。 經(jīng)常有香客問我镰绎,道長脓斩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任畴栖,我火速辦了婚禮随静,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吗讶。我一直安慰自己燎猛,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布照皆。 她就那樣靜靜地躺著重绷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪膜毁。 梳的紋絲不亂的頭發(fā)上昭卓,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天愤钾,我揣著相機(jī)與錄音,去河邊找鬼候醒。 笑死能颁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的倒淫。 我是一名探鬼主播伙菊,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼昌简!你這毒婦竟也來了占业?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤纯赎,失蹤者是張志新(化名)和其女友劉穎谦疾,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體犬金,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡念恍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了晚顷。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片峰伙。...
    茶點(diǎn)故事閱讀 38,622評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖该默,靈堂內(nèi)的尸體忽然破棺而出瞳氓,到底是詐尸還是另有隱情,我是刑警寧澤栓袖,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布匣摘,位于F島的核電站,受9級特大地震影響裹刮,放射性物質(zhì)發(fā)生泄漏音榜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一捧弃、第九天 我趴在偏房一處隱蔽的房頂上張望赠叼。 院中可真熱鬧,春花似錦违霞、人聲如沸嘴办。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽涧郊。三九已至,卻和暖如春癞谒,著一層夾襖步出監(jiān)牢的瞬間底燎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工弹砚, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留双仍,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓桌吃,卻偏偏與公主長得像朱沃,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子茅诱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容