寫(xiě)給大忙人的javaSE8(2)-常用流操作

如果前方的路是黑暗的,那應(yīng)該先找到指路的燈

java8中的 StreamAPI 非常豐富,本文介紹幾種比較重要的API。

  1. collect(toList()) 這個(gè)方法是用于生成一個(gè)列表, 是一個(gè)及早求值操作.
    下面看一段示例代碼
List<String> collected = Stream.of("a", "b", "c").
    collect(Collectors.toList());

assertEquals(Arrays.asList("a", "b", "c"), collected);

上一篇文章中說(shuō)過(guò),Stream中的很多操作都是惰性求值,因此在Stream中的一系列方法之后,需要調(diào)用一個(gè)collect的及早求值方法,從而得到一個(gè)List<String>,下面這句是用斷言測(cè)試工具測(cè)試結(jié)果是否為預(yù)期的。

  1. map操作可以將一個(gè)流中的值轉(zhuǎn)換成一個(gè)新的流
    下面看一段示例代碼
//使用map操作
List<String> collected = Stream.of("a", "b", "hello")
        .map(str -> str.toUpperCase()).collect(Collectors.toList());

assertEquals(Arrays.asList("A", "B", "HELLO"), collected);

傳給map的lambda表達(dá)式只接受一個(gè)String類(lèi)型的參數(shù),返回一個(gè)新的String。參數(shù)和返回值不必屬于同一種類(lèi)型,但是lambda表達(dá)式必須是Function接口的一個(gè)實(shí)例,F(xiàn)unction接口是只包含一個(gè)參數(shù)的普通函數(shù)接口。
map操作一開(kāi)始理解起來(lái)有點(diǎn)抽象。 在看看下面這個(gè)例子

//使用map操作
List<Integer> collected2 = Stream.of(1, 2, 3).map(i32 -> i32 + 1)
        .collect(Collectors.toList());
collected2.stream().forEach(i32 -> {
    System.out.println(i32);
});

assertEquals(Arrays.asList(2, 3, 4), collected2);

這里通過(guò)實(shí)現(xiàn)map中的 Function接口,來(lái)對(duì)數(shù)據(jù)進(jìn)行 +1 的操作。

3.filter 遍歷數(shù)據(jù)并檢查其中的元素。

//使用filter操作
List<String> beginningWithNumbers = Stream.of("a", "abc", "1abc").
        filter(value -> isDigit(value.charAt(0))).collect(Collectors.toList());
assertEquals(Arrays.asList("1abc"), beginningWithNumbers);

和map很像, filter接收一個(gè)函數(shù)作為參數(shù),該函數(shù)用lambda表達(dá)式表示。該函數(shù)和前面實(shí)例中if條件判斷語(yǔ)句的功能一樣,如果字符串首字母為數(shù)字,則返回true,因此若要重構(gòu)遺留的代碼,for循環(huán)中的if條件語(yǔ)句就可以用filter方法替代。

  1. flatMap
    前面的map操作,它可用一個(gè)新的值代替Stream中的值,但有時(shí),用戶希望讓map操作有點(diǎn)變化,生成一個(gè)新的Stream對(duì)象代替它,但是又不希望結(jié)果是一連串的流,此時(shí)flatMap最能派上用場(chǎng)。 看下面的例子。
//使用flatMap
List<Integer> together = Stream.of(Arrays.asList(1, 2), Arrays.asList(3, 4))
        .flatMap(numbers -> numbers.stream()).
collect(Collectors.toList());

assertEquals(Arrays.asList(1, 2, 3, 4), together);

用flatMap實(shí)際上是將每個(gè)列表轉(zhuǎn)換成 Stream對(duì)象,其余部分由flatMap方法處理。flatMap方法相關(guān)函數(shù)接口和map方法一樣, 都是 Function接口,只是方法的返回值限定為Stream類(lèi)型了。通俗一點(diǎn)的講,就是將參數(shù)都轉(zhuǎn)換成stream,形成了一個(gè)stream在通過(guò)及早求執(zhí)方法 collect()得到一個(gè) together的 List<Integer>

  1. max 和 min操作。

max和min是Stream上比較常用的操作。例如下代碼中,找到track中字段num值最小的一條

List<Track> tracks = Arrays.asList(
        new Track("第二天堂", 15),
        new Track("大將軍", 8),
        new Track("荒野獵人", 20));
Track shortestTrack = tracks.stream()
        .min(Comparator.comparing(track -> track.getNum())).get();

assertEquals(tracks.get(1), shortestTrack);

max或min方法需要指定一個(gè)排序指標(biāo)作為甄選依據(jù),示例代碼中我們指定了num字段作為排序依據(jù),同理,需要獲取最大值時(shí),只需要改用max方法即可。為了讓Stream對(duì)象按照track的長(zhǎng)度進(jìn)行排序,需要傳一個(gè)Comparator對(duì)象,java8 中提供了一個(gè)新的靜態(tài)方法, comparing,使用它可以方便地實(shí)現(xiàn)一個(gè)比較器。
6.reduce操作
reduce操作可以實(shí)現(xiàn)從一組值中生成一個(gè)值,實(shí)際上 count ,max,min等因?yàn)楸容^常用,所以被納入了標(biāo)準(zhǔn)庫(kù)中,其實(shí)這些方法都是reduce操作,先看一段代碼

//點(diǎn)定義一個(gè) BinaryOperator并指定它的結(jié)果是由 第一個(gè)參數(shù)+第二個(gè)參數(shù)組成的
BinaryOperator<Integer> accumulator = (acc, element) -> acc + element;
//緊接著,模擬每一次的操作
int count2 = accumulator.
  apply(accumulator.
                apply(accumulator.
                              apply(0, 1)
                , 2)
  , 3);

這里先從最內(nèi)部開(kāi)始,第一個(gè)值 0,1相加得到1,第二層 1,2 相加得到3 ,最外面一層,3加3等于6,實(shí)際上,他的操作方式就是我們?cè)谏厦娲a第一行定義的。 然后改成使用reduce方式在看看代碼是怎么實(shí)現(xiàn)的呢?

int count = Stream.of(1, 2, 3).reduce(0, (acc, element) -> acc + element);

在使用Stream的reduce操作時(shí),實(shí)際上就是將集合中的參數(shù),以0為起點(diǎn),按照兩個(gè)參數(shù)傳入Stream中的當(dāng)前元素和 acc。將兩個(gè)參數(shù)相加,acc在這里實(shí)際上就是累加器,保存著當(dāng)前的累加結(jié)果。
此類(lèi)的計(jì)算方式,在引入java8之前,我們還需要使用for循環(huán),另外定義一個(gè)累加器,每次循環(huán)取出數(shù)據(jù)進(jìn)行累加,并更新打累加器。 如果使用了reduce方式,是不是方便了很多呢。

其實(shí)我們也可以通過(guò)reduce來(lái)實(shí)現(xiàn)諸如 max, min的方法

int max = Stream.of(1,2,3).reduce(0, (acc, element) -> acc>element?acc:element);
System.out.println(max);
int min = Stream.of(1, 2, 3).reduce(0, (acc, element) -> acc<element?acc:element);
System.out.println(min);
你值得擁有最好的自己
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • pyspark.sql模塊 模塊上下文 Spark SQL和DataFrames的重要類(lèi): pyspark.sql...
    mpro閱讀 9,916評(píng)論 0 13
  • Jav8中,在核心類(lèi)庫(kù)中引入了新的概念,流(Stream)。流使得程序媛們得以站在更高的抽象層次上對(duì)集合進(jìn)行操作。...
    仁昌居士閱讀 4,077評(píng)論 0 6
  • Java8 in action 沒(méi)有共享的可變數(shù)據(jù),將方法和函數(shù)即代碼傳遞給其他方法的能力就是我們平常所說(shuō)的函數(shù)式...
    鐵牛很鐵閱讀 1,358評(píng)論 1 2
  • Java 8函數(shù)式編程學(xué)習(xí)筆記 author:Gavin date:2018/11/09 什么是函數(shù)式編程 在思考...
    安靜點(diǎn)就睡吧閱讀 1,355評(píng)論 0 10
  • 目錄結(jié)構(gòu) 介紹 Java語(yǔ)言的新特性2.1 Lambdas表達(dá)式與Functional接口2.2 接口的默認(rèn)與靜態(tài)...
    夜風(fēng)月圓閱讀 574評(píng)論 0 2

友情鏈接更多精彩內(nèi)容