java8之二——使用流

二嚷缭、流處理
1、流的概念
流:從支持?jǐn)?shù)據(jù)操作的源耍贾,生產(chǎn)而來的元素序列阅爽。
這里源可以是集合,輸入/數(shù)據(jù)流等荐开,有序序列生成的元素序列仍保持之前的順序付翁。
流操作分為中間操作和終端操作,可以順序執(zhí)行也可以并行執(zhí)行晃听。
流操作特點(diǎn):流水線百侧、內(nèi)部迭代(相比之前為外部迭代或顯式迭代)。


圖片.png

注意:終端操作只能進(jìn)行一次能扒,如不能forEach后再次forEach

public static List<String> getLowCaloricDishesNamesInJava8(List<Dish> dishes){
        return dishes.stream()
                .filter(d -> d.getCalories() < 400)
                .sorted(comparing(Dish::getCalories))
                .map(Dish::getName)
                .collect(toList());
    }

流的性能問題:http://www.importnew.com/17262.html

2佣渴、 常用流操作
(1)篩選切片
Streams接口支持filter方法,該接收接收一個(gè)謂詞(返回boolean的函數(shù))作為參數(shù)初斑,返回一個(gè)符合謂詞的元素的流辛润。如:

 // Filtering unique elements
        List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
        numbers.stream()
               .filter(i -> i % 2 == 0)
               .distinct()//對元素做去重
               .forEach(System.out::println);

        // Truncating a stream
        List<Dish> dishesLimit3 =
            menu.stream()
                .filter(d -> d.getCalories() > 300)
                .limit(3)//返回流的前3個(gè)
                .collect(toList());

        dishesLimit3.forEach(System.out::println);

        // Skipping elements
        List<Dish> dishesSkip2 =
            menu.stream()
                .filter(d -> d.getCalories() > 300)
                .skip(2)//返回流的后2個(gè)
                .collect(toList());

        dishesSkip2.forEach(System.out::println);

(2)映射:map與flatmap
StreamAPI的map方法、flatMap對流中每個(gè)元素應(yīng)用函數(shù)见秤,不同之處在于flatMap將流中每個(gè)元素轉(zhuǎn)化一個(gè)流砂竖,然后把所有流連成一個(gè)流(扁平化)。

 // map
        List<String> dishNames = menu.stream()
                                     .map(Dish::getName)
                                     .collect(toList());
        System.out.println(dishNames);

        // map
        List<String> words = Arrays.asList("Hello", "World");
        List<Integer> wordLengths = words.stream()
                                         .map(String::length)
                                         .collect(toList());//通過collect將流Stream轉(zhuǎn)成集合
        System.out.println(wordLengths);

        // flatMap
        words.stream()
                 .flatMap((String line) -> Arrays.stream(line.split("")))
                 .distinct()
                 .forEach(System.out::println);

        // flatMap
        List<Integer> numbers1 = Arrays.asList(1,2,3,4,5);
        List<Integer> numbers2 = Arrays.asList(6,7,8);
        List<int[]> pairs =
                        numbers1.stream()
                                .flatMap((Integer i) -> numbers2.stream()
                                                       .map((Integer j) -> new int[]{i, j})
                                 )
                                .filter(pair -> (pair[0] + pair[1]) % 3 == 0)
                                .collect(toList());
        pairs.forEach(pair -> System.out.println("(" + pair[0] + ", " + pair[1] + ")"));
        //輸出(1,8)鹃答、(2,7)乎澄、(3,6)
Paste_Image.png
Paste_Image.png

(3)查找和匹配
StreamAPI提供方法:
allMatch:檢查謂詞是否匹配所有元素
anyMatch:檢查謂詞是否至少匹配一個(gè)元素
noneMatch:相對于allMatch,檢查流中沒有任何元素和謂詞匹配

findAny:返回流中任意元素
findFirst:查找流中第一個(gè)元素

public static void main(String...args){
        if(isVegetarianFriendlyMenu()){
            System.out.println("Vegetarian friendly");
        }

        System.out.println(isHealthyMenu());
        System.out.println(isHealthyMenu2());
        
        Optional<Dish> dish = findVegetarianDish();
        dish.ifPresent(d -> System.out.println(d.getName()));
    }
    
    private static boolean isVegetarianFriendlyMenu(){
        return menu.stream().anyMatch(Dish::isVegetarian);
    }
    
    private static boolean isHealthyMenu(){
        return menu.stream().allMatch(d -> d.getCalories() < 1000);
    }
    
    private static boolean isHealthyMenu2(){
        return menu.stream().noneMatch(d -> d.getCalories() >= 1000);
    }
    
   //findAny返回一個(gè)Optional容器實(shí)例测摔,找不到元素避免使用null
   //isPresent :Optional有值返回true
   //ifPresent:有值時(shí)執(zhí)行其中代碼塊
    private static Optional<Dish> findVegetarianDish(){
        return menu.stream().filter(Dish::isVegetarian).findAny();
    }

(4)規(guī)約
reduce操作將流中所有元素反復(fù)結(jié)合置济。

public static void main(String...args){

        List<Integer> numbers = Arrays.asList(3,4,5,1,2);
        int sum = numbers.stream().reduce(0, (a, b) -> a + b);//求和
        System.out.println(sum);

        int sum2 = numbers.stream().reduce(0, Integer::sum);
        System.out.println(sum2);

        int max = numbers.stream().reduce(0, (a, b) -> Integer.max(a, b));
        System.out.println(max);

        Optional<Integer> min = numbers.stream().reduce(Integer::min);
        min.ifPresent(System.out::println);
        //沒有初始值,流為空則沒有返回避咆,因此返回使用Optional

        int calories = menu.stream()
                           .map(Dish::getCalories)
                           .reduce(0, Integer::sum);
        System.out.println("Number of calories:" + calories);
    }
Paste_Image.png

(5)數(shù)值流:
java8引入三個(gè)原始類型特化流IntStream舟肉、DoubleStream、LongSteam查库,分別將流中元素特化為int路媚、long、double樊销。
boxed()方法則對原始類型進(jìn)行裝箱整慎。
數(shù)值流自帶sum脏款、max、min裤园、average等方法撤师。

int calories = menu.stream()
                           .mapToInt(Dish::getCalories)
                           .sum();
        System.out.println("Number of calories:" + calories);


        // max and OptionalInt
        OptionalInt maxCalories = menu.stream()                                                      
                                      .mapToInt(Dish::getCalories)
                                      .max();

        int max = maxCalories.orElse(1);//沒有最大值,設(shè)置默認(rèn)值1

        // numeric ranges
        IntStream evenNumbers = IntStream.rangeClosed(1, 100)
                                 .filter(n -> n % 2 == 0);
       //rangeClosed包含結(jié)束值拧揽,而range不包含結(jié)束值

        System.out.println(evenNumbers.count());
        
        //返回(1,100)符合勾股定理的三元組
        Stream<int[]> pythagoreanTriples =
               IntStream.rangeClosed(1, 100).boxed()
                        .flatMap(a -> IntStream.rangeClosed(a, 100)
                                               .mapToObj(b -> new int[]{a, b, (int) Math.sqrt(a * a + b * b)})
                                               .filter(t -> t[2] % 1 == 0)
                                               );       
        pythagoreanTriples.forEach(t -> System.out.println(t[0] + ", " + t[1] + ", " + t[2])); 

(6)構(gòu)建流
流可以由值剃盾、數(shù)組、文件創(chuàng)建

        // Stream.of
        Stream<String> stream = Stream.of("Java 8", "Lambdas", "In", "Action");
        stream.map(String::toUpperCase).forEach(System.out::println);

        // Stream.empty
        Stream<String> emptyStream = Stream.empty();

        // Arrays.stream
        int[] numbers = {2, 3, 5, 7, 11, 13};
        System.out.println(Arrays.stream(numbers).sum());
       
       //文件流回自動(dòng)關(guān)閉
       long uniqueWords = Files.lines(Paths.get("lambdasinaction/chap5/data.txt"), Charset.defaultCharset())
                                 .flatMap(line -> Arrays.stream(line.split(" ")))//生成單詞流
                                 .distinct()
                                 .count();//

         System.out.println("There are " + uniqueWords + " unique words in data.txt");

可以由于Stream.iterate和Stream.generate函數(shù)生成無限流(沒有固定大小)

        // Stream.iterate
        Stream.iterate(0, n -> n + 2)
              .limit(10)
              .forEach(System.out::println);

        // fibonnaci with iterate
        Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1],t[0] + t[1]})
              .limit(10)
              .forEach(t -> System.out.println("(" + t[0] + ", " + t[1] + ")"));
        
        Stream.iterate(new int[]{0, 1}, t -> new int[]{t[1],t[0] + t[1]})
              .limit(10)
              . map(t -> t[0])  
              .forEach(System.out::println);

        // random stream of doubles with Stream.generate
        Stream.generate(Math::random)
              .limit(10)
              .forEach(System.out::println);
 
        // stream of 1s with Stream.generate
        IntStream.generate(() -> 1)
                 .limit(5)
                 .forEach(System.out::println);

        IntStream.generate(new IntSupplier(){
            public int getAsInt(){
                return 2;
            }
        }).limit(5)
          .forEach(System.out::println);
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末淤袜,一起剝皮案震驚了整個(gè)濱河市痒谴,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌铡羡,老刑警劉巖积蔚,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異烦周,居然都是意外死亡尽爆,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門读慎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來漱贱,“玉大人,你說我怎么就攤上這事贪壳”ヒ冢” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵闰靴,是天一觀的道長。 經(jīng)常有香客問我钻注,道長蚂且,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任幅恋,我火速辦了婚禮杏死,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘捆交。我一直安慰自己淑翼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布品追。 她就那樣靜靜地躺著玄括,像睡著了一般。 火紅的嫁衣襯著肌膚如雪肉瓦。 梳的紋絲不亂的頭發(fā)上遭京,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天胃惜,我揣著相機(jī)與錄音,去河邊找鬼哪雕。 笑死船殉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的斯嚎。 我是一名探鬼主播利虫,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼堡僻!你這毒婦竟也來了糠惫?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤苦始,失蹤者是張志新(化名)和其女友劉穎寞钥,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體陌选,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡理郑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了咨油。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片您炉。...
    茶點(diǎn)故事閱讀 39,711評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖役电,靈堂內(nèi)的尸體忽然破棺而出赚爵,到底是詐尸還是另有隱情,我是刑警寧澤法瑟,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布冀膝,位于F島的核電站,受9級特大地震影響霎挟,放射性物質(zhì)發(fā)生泄漏窝剖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一酥夭、第九天 我趴在偏房一處隱蔽的房頂上張望赐纱。 院中可真熱鬧,春花似錦熬北、人聲如沸疙描。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽起胰。三九已至,卻和暖如春整份,著一層夾襖步出監(jiān)牢的瞬間待错,已是汗流浹背籽孙。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留火俄,地道東北人犯建。 一個(gè)月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像瓜客,于是被迫代替她去往敵國和親适瓦。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評論 2 353

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

  • 概要 流讓你從外部迭代轉(zhuǎn)向內(nèi)部迭代谱仪。這樣玻熙,你就用不著寫下面這樣的代碼來顯式地管理數(shù)據(jù)集合的迭代(外部迭代)了: 現(xiàn)...
    潯它芉咟渡閱讀 1,499評論 1 2
  • Java8 in action 沒有共享的可變數(shù)據(jù),將方法和函數(shù)即代碼傳遞給其他方法的能力就是我們平常所說的函數(shù)式...
    鐵牛很鐵閱讀 1,229評論 1 2
  • 第一章 為什么要關(guān)心Java 8 使用Stream庫來選擇最佳低級執(zhí)行機(jī)制可以避免使用Synchronized(同...
    謝隨安閱讀 1,491評論 0 4
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理疯攒,服務(wù)發(fā)現(xiàn)嗦随,斷路器,智...
    卡卡羅2017閱讀 134,651評論 18 139
  • 原本按照自己的習(xí)慣,我是要等到我胡的獵場播完以后再看的砂吞,誰曾想最重要的人都告訴我署恍,獵場開播了,看了蜻直,之類的...
    快樂的老三閱讀 221評論 0 3