java stream 1 操作符

操作符

什么是操作符呢岂傲?操作符就是對(duì)數(shù)據(jù)進(jìn)行的一種處理工作痰洒,一道加工程序麦向;就好像工廠的工人對(duì)流水線上的產(chǎn)品進(jìn)行一道加工程序一樣瘟裸。

image

Stream的操作符大體上分為兩種:中間操作符終止操作符

中間操作符

對(duì)于數(shù)據(jù)流來(lái)說(shuō),中間操作符在執(zhí)行制定處理程序后诵竭,數(shù)據(jù)流依然可以傳遞給下一級(jí)的操作符话告。

中間操作符包含8種(排除了parallel,sequential,這兩個(gè)操作并不涉及到對(duì)數(shù)據(jù)流的加工操作):

  1. map(mapToInt,mapToLong,mapToDouble) 轉(zhuǎn)換操作符,把比如A->B卵慰,這里默認(rèn)提供了轉(zhuǎn)int沙郭,long,double的操作符裳朋。
  2. flatmap(flatmapToInt,flatmapToLong,flatmapToDouble) 拍平操作比如把 int[]{2,3,4} 拍平 變成 2病线,3,4 也就是從原來(lái)的一個(gè)數(shù)據(jù)變成了3個(gè)數(shù)據(jù),這里默認(rèn)提供了拍平成int,long,double的操作符送挑。
  3. limit 限流操作绑莺,比如數(shù)據(jù)流中有10個(gè) 我只要出前3個(gè)就可以使用。
  4. distint 去重操作惕耕,對(duì)重復(fù)元素去重纺裁,底層使用了equals方法。
  5. filter 過(guò)濾操作赡突,把不想要的數(shù)據(jù)過(guò)濾对扶。
  6. peek 挑出操作,如果想對(duì)數(shù)據(jù)進(jìn)行某些操作惭缰,如:讀取浪南、編輯修改等。
  7. skip 跳過(guò)操作漱受,跳過(guò)某些元素络凿。
  8. sorted(unordered) 排序操作,對(duì)元素排序昂羡,前提是實(shí)現(xiàn)Comparable接口絮记,當(dāng)然也可以自定義比較器。

終止操作符

數(shù)據(jù)經(jīng)過(guò)中間加工操作虐先,就輪到終止操作符上場(chǎng)了怨愤;終止操作符就是用來(lái)對(duì)數(shù)據(jù)進(jìn)行收集或者消費(fèi)的,數(shù)據(jù)到了終止操作這里就不會(huì)向下流動(dòng)了蛹批,終止操作符只能使用一次撰洗。

  1. collect 收集操作,將所有數(shù)據(jù)收集起來(lái)腐芍,這個(gè)操作非常重要差导,官方的提供的Collectors 提供了非常多收集器,可以說(shuō)Stream 的核心在于Collectors猪勇。
  2. count 統(tǒng)計(jì)操作设褐,統(tǒng)計(jì)最終的數(shù)據(jù)個(gè)數(shù)。
  3. findFirst泣刹、findAny 查找操作助析,查找第一個(gè)、查找任何一個(gè) 返回的類型為Optional椅您。
  4. noneMatch外冀、allMatch、anyMatch 匹配操作襟沮,數(shù)據(jù)流中是否存在符合條件的元素 返回值為bool 值。
  5. min、max 最值操作开伏,需要自定義比較器膀跌,返回?cái)?shù)據(jù)流中最大最小的值。
  6. reduce 規(guī)約操作固灵,將整個(gè)數(shù)據(jù)流的值規(guī)約為一個(gè)值,count、min捏卓、max底層就是使用reduce逗栽。
  7. forEach、forEachOrdered 遍歷操作仍秤,這里就是對(duì)最終的數(shù)據(jù)進(jìn)行消費(fèi)了熄诡。
  8. toArray 數(shù)組操作,將數(shù)據(jù)流的元素轉(zhuǎn)換成數(shù)組诗力。

這里只介紹了Stream凰浮,并沒(méi)有涉及到IntStreamLongStream苇本、DoubleStream袜茧,這三個(gè)流實(shí)現(xiàn)了一些特有的操作符,我將在后續(xù)文章中介紹到瓣窄。

說(shuō)了這么多笛厦,只介紹這些操作符還遠(yuǎn)遠(yuǎn)不夠;俗話說(shuō)俺夕,實(shí)踐出真知裳凸。那么,Let‘s go啥么。

代碼演練

Stream 的一系列操作必須要使用終止操作登舞,否者整個(gè)數(shù)據(jù)流是不會(huì)流動(dòng)起來(lái)的,即處理操作不會(huì)執(zhí)行悬荣。

  • map菠秒,可以看到 map 操作符要求輸入一個(gè)Function的函數(shù)是接口實(shí)例,功能是將T類型轉(zhuǎn)換成R類型的氯迂。
image

map操作將原來(lái)的單詞 轉(zhuǎn)換成了每個(gè)單的長(zhǎng)度践叠,利用了String自身的length()方法,該方法返回類型為int嚼蚀。這里我直接使用了lambda表達(dá)式禁灼,關(guān)于lambda表達(dá)式 還請(qǐng)讀者們自行了解吧。

public class Main {

    public static void main(String[] args) {
        Stream.of("apple","banana","orange","waltermaleon","grape")
                .map(e->e.length()) //轉(zhuǎn)成單詞的長(zhǎng)度 int
                .forEach(e->System.out.println(e)); //輸出
    }
}

當(dāng)然也可以這樣轿曙,這里使用了成員函數(shù)引用弄捕,為了便于讀者們理解僻孝,后續(xù)的例子中將使用lambda表達(dá)式而非函數(shù)引用。

public class Main {

    public static void main(String[] args) {
         Stream.of("apple","banana","orange","waltermaleon","grape")
                .map(String::length) //轉(zhuǎn)成單詞的長(zhǎng)度 int
                .forEach(System.out::println);
    }
}

結(jié)果如圖:

image
  • mapToInt 將數(shù)據(jù)流中得元素轉(zhuǎn)成Int守谓,這限定了轉(zhuǎn)換的類型Int穿铆,最終產(chǎn)生的流為IntStream,及結(jié)果只能轉(zhuǎn)化成int斋荞。
image
public class Main {

    public static void main(String[] args) {
         Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
                .mapToInt(e -> e.length()) //轉(zhuǎn)成int
                .forEach(e -> System.out.println(e));
    }
}

mapToInt如圖:

image
  • mapToLong荞雏、mapToDouble 與mapToInt 類似
public class Main {

    public static void main(String[] args) {
         Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
                .mapToLong(e -> e.length()) //轉(zhuǎn)成long ,本質(zhì)上是int 但是存在類型自動(dòng)轉(zhuǎn)換
                .forEach(e -> System.out.println(e));
    }
}

mapToLong 如圖:

image
public class Main {

    public static void main(String[] args) {
         Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
                .mapToDouble(e -> e.length()) //轉(zhuǎn)成Double ,自動(dòng)類型轉(zhuǎn)換成Double
                .forEach(e -> System.out.println(e));
    }
}

mapToDouble如圖:

image
  • flatmap 作用就是將元素拍平拍扁 平酿,將拍扁的元素重新組成Stream凤优,并將這些Stream 串行合并成一條Stream
image
public class Main {

    public static void main(String[] args) {
        Stream.of("a-b-c-d","e-f-i-g-h")
                .flatMap(e->Stream.of(e.split("-")))
                .forEach(e->System.out.println(e));

    }
}

flatmap 如圖:

image
  • flatmapToInt、flatmapToLong蜈彼、flatmapToDouble 跟flatMap 都類似的筑辨,只是類型被限定了,這里就不在舉例子了柳刮。

  • limit 限制元素的個(gè)數(shù)挖垛,只需傳入 long 類型 表示限制的最大數(shù)

public class Main {

    public static void main(String[] args) {
        Stream.of(1,2,3,4,5,6)
                .limit(3) //限制三個(gè)
                .forEach(e->System.out.println(e)); //將輸出 前三個(gè) 1,2秉颗,3
    }
}

limit如圖:

image
  • distinct 將根據(jù)equals 方法進(jìn)行判斷痢毒,如果要對(duì)自己自定義的bean 去重,則需要 重寫(xiě)equals方法蚕甥,但是這不是唯一的方法哪替,后面文章我將帶大家實(shí)現(xiàn)自定義(bean 的某個(gè)字段去重)去重。
image
public class Main {

    public static void main(String[] args) {

        Stream.of(1,2,3,1,2,5,6,7,8,0,0,1,2,3,1)
                .distinct() //去重
                .forEach(e->System.out.println(e));

    }
}

distinct 如圖:

image
  • filter 對(duì)某些元素進(jìn)行過(guò)濾菇怀,不符合篩選條件的將無(wú)法進(jìn)入流的下游
public class Main {

    public static void main(String[] args) {
        Stream.of(1,2,3,1,2,5,6,7,8,0,0,1,2,3,1)
                .filter(e->e>=5) //過(guò)濾小于5的
                .forEach(e->System.out.println(e));
    }
}

filter 如圖:

image
  • peek 挑選 凭舶,將元素挑選出來(lái),可以理解為提前消費(fèi)
public class Main {

    public static void main(String[] args) {

        User w = new User("w",10);
        User x = new User("x",11);
        User y = new User("y",12);

        Stream.of(w,x,y)
                .peek(e->{e.setName(e.getAge()+e.getName());}) //重新設(shè)置名字 變成 年齡+名字
                .forEach(e->System.out.println(e.toString()));

    }

    static class User {

        private String name;

        private int age;

        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }

        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;
        }

        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

}

peek 如圖:

image
  • skip 跳過(guò) 元素
public class Main {

    public static void main(String[] args) {
        Stream.of(1,2,3,4,5,6,7,8,9)
                .skip(4) //跳過(guò)前四個(gè)
                .forEach(e->System.out.println(e)); //輸出的結(jié)果應(yīng)該只有5爱沟,6帅霜,7,8呼伸,9
    }
}

skip 如圖:

image
  • sorted 排序 底層依賴Comparable 實(shí)現(xiàn)身冀,也可以提供自定義比較器

這里Integer 實(shí)現(xiàn)了比較器

public class Main {

    public static void main(String[] args) {
        Stream.of(2,1,3,6,4,9,6,8,0)
                .sorted()
                .forEach(e->System.out.println(e));
    }
}

sorted 默認(rèn)比較器如圖:

image

這里使用自定義比較,當(dāng)然User 可以實(shí)現(xiàn)Comparable 接口

public class Main {

    public static void main(String[] args) {

        User x = new User("x",11);
        User y = new User("y",12);
        User w = new User("w",10);

        Stream.of(w,x,y)
                .sorted((e1,e2)->e1.age>e2.age?1:e1.age==e2.age?0:-1)
                .forEach(e->System.out.println(e.toString()));

    }

    static class User {

        private String name;

        private int age;

        public User(String name, int age) {
            this.name = name;
            this.age = age;
        }

        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;
        }

        @Override
        public String toString() {
            return "User{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    '}';
        }
    }

}

如圖:

image
  • collect 收集括享,使用系統(tǒng)提供的收集器可以將最終的數(shù)據(jù)流收集到List搂根,Set,Map等容器中铃辖。

這里我使用collect 將元素收集到一個(gè)set中

public class Main {

    public static void main(String[] args) {
        Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
                .collect(Collectors.toSet()) //set 容器
                .forEach(e -> System.out.println(e));
    }
}

咦剩愧?,不是說(shuō)終止操作符只能使用一次嗎娇斩,為什么這里調(diào)用了forEach 呢仁卷?forEach不僅僅是是Stream 中得操作符還是各種集合中得一個(gè)語(yǔ)法糖穴翩,不信咋們?cè)囋嚒?/p>

public class Main {

    public static void main(String[] args) {

        Set<String> stringSet = Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
                .collect(Collectors.toSet()); //收集的結(jié)果就是set
        stringSet.forEach(e->System.out.println(e)); set的語(yǔ)法糖forEach
}

結(jié)果如圖:

image
  • count 統(tǒng)計(jì)數(shù)據(jù)流中的元素個(gè)數(shù),返回的是long 類型
public class Main {

    public static void main(String[] args) {

        long count = Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
                .count();

        System.out.println(count);
    }
}

count 如圖:

image
  • findFirst 獲取流中的第一個(gè)元素

這里找到第一個(gè)元素 apple

public class FindFirst {

    public static void main(String[] args) {
        Optional<String> stringOptional = Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
                .findFirst();
        stringOptional.ifPresent(e->System.out.println(e));
    }
}

findFirst 結(jié)果如圖:

image
  • findAny 獲取流中任意一個(gè)元素
public class FindAny {

    public static void main(String[] args) {
        Optional<String> stringOptional = Stream.of("apple", "banana", "orange", "waltermaleon", "grape")
                .parallel()
                .findAny(); //在并行流下每次返回的結(jié)果可能一樣也可能不一樣
        stringOptional.ifPresent(e->System.out.println(e));
    }
}

findAny 在并行流下 使用結(jié)果:

輸出了orange

image

輸出了banana

image
  • noneMatch 數(shù)據(jù)流中得沒(méi)有一個(gè)元素與條件匹配的

這里 的作用是是判斷數(shù)據(jù)流中 一個(gè)都沒(méi)有與aa 相等元素 锦积,但是流中存在 aa 藏否,所以最終結(jié)果應(yīng)該是false

public class NoneMatch {

    public static void main(String[] args) {
        boolean result = Stream.of("aa","bb","cc","aa")
                .noneMatch(e->e.equals("aa"));
        System.out.println(result);
    }
}

noneMatch 如圖:

image
  • allMatch和anyMatch 一個(gè)是全匹配,一個(gè)是任意匹配 和noneMatch 類似充包,這里就不在舉例了。
  • min 最小的一個(gè)遥椿,傳入比較器基矮,也可能沒(méi)有(如果數(shù)據(jù)流為空)
public class Main {

    public static void main(String[] args) {

        Optional<Integer> integerOptional = Stream.of(0,9,8,4,5,6,-1)
                .min((e1,e2)->e1.compareTo(e2));

        integerOptional.ifPresent(e->System.out.println(e));

    }

min如圖:

image
  • max 元素中最大的,需要傳入比較器冠场,也可能沒(méi)有(流為Empty時(shí))
public class Main {

    public static void main(String[] args) {

        Optional<Integer> integerOptional = Stream.of(0,9,8,4,5,6,-1)
                .max((e1,e2)->e1.compareTo(e2));

        integerOptional.ifPresent(e->System.out.println(e));

    }
}

max 如圖:

image
  • reduce 是一個(gè)規(guī)約操作家浇,所有的元素歸約成一個(gè),比如對(duì)所有元素求和碴裙,乘啊等钢悲。

這里實(shí)現(xiàn)了一個(gè)加法,指定了初始化的值

public class Main {
    public static void main(String[] args) {

        int sum = Stream.of(0,9,8,4,5,6,-1)
              .reduce(0,(e1,e2)->e1+e2);
        System.out.println(sum);
    }
}

reduce 如圖:

image
  • forEach

forEach 其實(shí)前就已經(jīng)見(jiàn)過(guò)了舔株,對(duì)每個(gè)數(shù)據(jù)遍歷迭代

  • forEachOrdered 適用用于并行流的情況下進(jìn)行迭代莺琳,能保證迭代的有序性

這里通過(guò)并行的方式輸出數(shù)字

public class ForEachOrdered {
    public static void main(String[] args) {
        Stream.of(0,2,6,5,4,9,8,-1)
                .parallel()
                .forEachOrdered(e->{
                    System.out.println(Thread.currentThread().getName()+": "+e);});
    }
}

forEachOrdered 如圖:

image
  • toArray 轉(zhuǎn)成數(shù)組,可以提供自定義數(shù)組生成器
public class ToArray {
    public static void main(String[] args) {
        Object[] objects=Stream.of(0,2,6,5,4,9,8,-1)
                .toArray();

        for (int i = 0; i < objects.length; i++) {
            System.out.println(objects[i]);
        }
    }
}

toArray 如圖:

image
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末载慈,一起剝皮案震驚了整個(gè)濱河市惭等,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌办铡,老刑警劉巖辞做,帶你破解...
    沈念sama閱讀 222,000評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異寡具,居然都是意外死亡秤茅,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)童叠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)框喳,“玉大人,你說(shuō)我怎么就攤上這事拯钻√” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,561評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵粪般,是天一觀的道長(zhǎng)拼余。 經(jīng)常有香客問(wèn)我,道長(zhǎng)亩歹,這世上最難降的妖魔是什么匙监? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,782評(píng)論 1 298
  • 正文 為了忘掉前任凡橱,我火速辦了婚禮,結(jié)果婚禮上亭姥,老公的妹妹穿的比我還像新娘稼钩。我一直安慰自己,他們只是感情好达罗,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,798評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布坝撑。 她就那樣靜靜地躺著,像睡著了一般粮揉。 火紅的嫁衣襯著肌膚如雪巡李。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,394評(píng)論 1 310
  • 那天扶认,我揣著相機(jī)與錄音侨拦,去河邊找鬼。 笑死辐宾,一個(gè)胖子當(dāng)著我的面吹牛狱从,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播叠纹,決...
    沈念sama閱讀 40,952評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼季研,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了誉察?” 一聲冷哼從身側(cè)響起训貌,我...
    開(kāi)封第一講書(shū)人閱讀 39,852評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎冒窍,沒(méi)想到半個(gè)月后递沪,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,409評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡综液,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,483評(píng)論 3 341
  • 正文 我和宋清朗相戀三年款慨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谬莹。...
    茶點(diǎn)故事閱讀 40,615評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡檩奠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出附帽,到底是詐尸還是另有隱情埠戳,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評(píng)論 5 350
  • 正文 年R本政府宣布蕉扮,位于F島的核電站整胃,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏喳钟。R本人自食惡果不足惜屁使,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,979評(píng)論 3 334
  • 文/蒙蒙 一在岂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蛮寂,春花似錦蔽午、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,470評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至范抓,卻和暖如春写半,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背尉咕。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,571評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留璃岳,地道東北人年缎。 一個(gè)月前我還...
    沈念sama閱讀 49,041評(píng)論 3 377
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像铃慷,于是被迫代替她去往敵國(guó)和親单芜。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,630評(píng)論 2 359

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