java8學(xué)習(xí)筆記

1.jpg

1.流

  • 流是java API的新成員,它允許以聲明式的方式處理數(shù)據(jù)集合(通過(guò)查詢(xún)語(yǔ)句來(lái)表達(dá),而不是臨時(shí)編寫(xiě)一個(gè)實(shí)現(xiàn)),可以把流看成遍歷數(shù)據(jù)集的高級(jí)迭代器
  • 流可以透明的并行處理

示例:

import static java.util.Comparator.comparing;
import static java.util.stream.Collectors.toList;
List<String> lowCaloricDishesName = menu.stream()
 .filter(d -> d.getCalories() < 400)  //選出400卡路里以下的菜肴
 .sorted(comparing(Dish::getCalories))  //按照卡路里排序
 .map(Dish::getName)   //提取菜肴的名稱(chēng)
 .limt(3)                             //截?cái)嗔?,使元素不超過(guò)給定數(shù)量
 .collect(toList());    //將所有的名稱(chēng)保存在List中

如果想利用多核架構(gòu)并行執(zhí)行這段代碼,只需要把stream()換成parallelStream();
因?yàn)閒ilter,sorted,map,collect等操作是與具體線程無(wú)關(guān)的高層次組件,所以他們內(nèi)部實(shí)現(xiàn)可以是單線程的,也可能透明的充分利用電腦的多核架構(gòu);

2.流與集合

集合和流之間的差異就在于什么時(shí)候進(jìn)行計(jì)算

  • 集合:集合是一個(gè)內(nèi)存中的數(shù)據(jù)結(jié)構(gòu),它包含數(shù)據(jù)結(jié)構(gòu)中目前所有的值,集合中的每個(gè)元素都得先計(jì)算出來(lái)才能添加到集合中(你可以往集合中添加元素或者刪除元素,但是不管什么時(shí)候,集合中的每個(gè)元素都是放在內(nèi)存中的,元素都得先計(jì)算出來(lái)才能成為集合的一部分)(供應(yīng)商驅(qū)動(dòng))
  • 流:流是在概念上固定的數(shù)據(jù)結(jié)構(gòu)(不能添加或者刪除元素)其元素按需計(jì)算,從另一個(gè)角度說(shuō),流就像是一個(gè)延遲創(chuàng)建的集合,只要在消費(fèi)者要求的時(shí)候才會(huì)計(jì)算值(需求驅(qū)動(dòng),實(shí)時(shí)制造)

2.1 流只能遍歷一次

3.流操作

QQ截圖20190419180918.png
  • filter、map和Limit可以連成一條流水線,稱(chēng)為中間操作
  • collect 觸發(fā)流水線執(zhí)行并且關(guān)閉它,稱(chēng)為終端操作,終端操作會(huì)從流水線生成結(jié)果,其結(jié)果是任何不是流的值,比如List,Integer甚至是void
long count = menu.stream()
 .filter(d -> d.getCalories() > 300)
 .distinct()
 .limit(3)
 .count();    //count操作返回的是一個(gè)long,不是流,所以是終端操作
QQ截圖20190419181827.png

4.使用流

4.1篩選、切片
  • 篩選信息---外部迭代
List<Dish> vegetarianDishes = new ArrayList<>();
for(Dish d: menu){
    if(d.isVegetarian()){
        vegetarianDishes.add(d);
   }
} 
  • 篩選信息---內(nèi)部迭代(Stream API)
import static java.util.stream.Collectors.toList;
List<Dish> vegetarianDishes = menu.stream().filter(Dish::isVegetarian).collect(toList());
  • 流支持distinct方法,過(guò)濾重復(fù)數(shù)據(jù)
//篩選出列表中所有的偶數(shù),并確保沒(méi)有重復(fù)
List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream()
 .filter(i -> i % 2 == 0)
 .distinct()        
 .forEach(System.out::println); 
  • 截?cái)嗔?-流支持limit(n)方法,返回一個(gè)不超過(guò)給定長(zhǎng)度的流,所需的長(zhǎng)度作為參數(shù)傳遞費(fèi)limit
List<Dish> dishes = menu.stream()
 .filter(d -> d.getCalories() > 300)              //卡路里大于300
 .limit(3)                               //符合卡路里大于300的前三個(gè)元素
 .collect(toList());                //終端操作,流轉(zhuǎn)化為L(zhǎng)ist
  • 跳過(guò)元素--流支持skip(n)方法,返回一個(gè)扔掉了前n個(gè)元素的流。如果元素不足n個(gè),則返回一個(gè)空流
List<Dish> dishes = menu.stream()
 .filter(d -> d.getCalories() > 300)
 .skip(2)     //跳過(guò)卡路里大于300的前兩個(gè)元素
 .collect(toList());

4.2 映射

4.2.1 對(duì)流中每一個(gè)元素應(yīng)用函數(shù)
  • 流支持Map方法,它會(huì)接受一個(gè)函數(shù)作為參數(shù)。這個(gè)函數(shù)會(huì)被應(yīng)用到每個(gè)元素上,并將其映射成一個(gè)新的元素
List<Integer> dishNameLengths = menu.stream()
 .map(Dish::getName)                    //map 提取名稱(chēng)
 .map(String::length)                      // 返回 名稱(chēng)長(zhǎng)度
 .collect(toList());                           //終端操作,流轉(zhuǎn)化為L(zhǎng)ist
4.2.2 流的扁平化
  • 使用flatMap方法--各個(gè)數(shù)組并不是分別映射成一個(gè)流,而是映射成流的內(nèi)容
/**
** 對(duì)于一張單詞表,如何返回一張列表,列出里面 各不相同的字符 呢?例如,給定單詞列表["Hello","World"],你想要返回列表["H","e","l", "o","W","r","d"]
**/
List<String> uniqueCharacters =
 words.stream()
 .map(w -> w.split(""))            //將每個(gè)單詞轉(zhuǎn)換成由其字母構(gòu)成的數(shù)組
 .flatMap(Arrays::stream)        //將各個(gè)生成流扁平化為單個(gè)流
 .distinct()
 .collect(Collectors.toList()); 

4.3查找和匹配

Stream API提供了allMatch,anyMatch,noneMatch,findFirst和findAny方法匹配數(shù)據(jù)集中的某些元素

4.3.1 檢查謂詞是否至少匹配一個(gè)元素
  • anyMatch方法--流中是否有一個(gè)元素能匹配給定的謂詞,該方法返回一個(gè)Boolean,因此是一個(gè)終端操作
if(menu.stream().anyMatch(Dish::isVegetarian)){
    System.out.println("The menu is (somewhat) vegetarian friendly!!");
} 
4.3.2 檢查謂詞是否匹配所有元素
  • allMatch方法的工作原理和anyMatch類(lèi)似,但它會(huì)看流中的元素是否都能匹配給定的謂詞
boolean isHealthy = menu.stream()
   .allMatch(d -> d.getCalories() < 1000);  //所有菜的熱量都低于1000卡路里 才返回true;
  • noneMatch方法--確保流中沒(méi)有任何元素與給定的謂詞匹配
boolean isHealthy = menu.stream()
 .noneMatch(d -> d.getCalories() >= 1000);  //所有菜的熱量都低于1000卡路里 才返回true;
  • anyMatch,allMatch和noneMatch這三個(gè)操作都用到了所謂的短路,相當(dāng)于java中&& 和 || 運(yùn)算符短路在流中的版本
4.3.3 查找元素
  • findAny 方法將返回當(dāng)前流中的任意元素
Optional<Dish> dish = menu.stream()
     .filter(Dish::isVegetarian)   //篩選素菜
     .findAny();  //找到一個(gè)立即結(jié)束流返回
  • Optional<T>類(lèi)(java.util.Optional)是一個(gè)容器類(lèi),代表一個(gè)值存在或不存在。在上面的代碼中,findAny可能什么元素都沒(méi)找到
4.3.4 查找第一個(gè)元素
List<Integer> someNumbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> firstSquareDivisibleByThree =
 someNumbers.stream()
 .map(x -> x * x)
 .filter(x -> x % 3 == 0)
 .findFirst(); // 9 

4.4 歸約

4.4.1元素求和
//reduce求和:第一個(gè)參數(shù)是求和初始值
List<Integer> numbers = Arrays.asList(5,7,9,12,45,67);
Integer total = numbers.stream().reduce(0, Integer::sum);  //145
//流中沒(méi)有任何元素,無(wú)法返回和的情況
List<Integer> numbers11 = Arrays.asList();
Optional<Integer> total1 = numbers11.stream().reduce(Integer::sum); //Optional.empty
4.4.2最大值和最小值
List<Integer> numbers = Arrays.asList(5,7,9,12,45,67);
Optional<Integer> max = numbers.stream().reduce(Integer::max);  //Optional[67]
Optional<Integer> min = numbers.stream().reduce(Integer::min);    //Optional[5]

示例:求數(shù)組大小

List<Integer> numbers = Arrays.asList(5,7,9,12,45,67);
Integer ArrayTotal = numbers.stream().map(e -> 1).reduce(0,Integer::sum); // 6
long count = numbers.stream().count(); 

以上代碼有一個(gè)問(wèn)題,它有一個(gè)暗含的裝箱成本,每個(gè)Integer都必須拆箱成一個(gè)原始類(lèi)型,在進(jìn)行求和

4.5 數(shù)值流

4.5.1原始類(lèi)型流特化

java8引入了三個(gè)原始類(lèi)型特化流接口來(lái)解決拆箱問(wèn)題:IntStream,DoubleStream和LongStream,分別將流中的元素特化為int,long和double,從而避免了暗含的裝箱成本。

1.映射到數(shù)值流

將流轉(zhuǎn)換為特定版本的常用方法是mapToInt,mapToDouble,mapToLong,這些方法和前面說(shuō)的map方法的工作方式一樣,只是返回的是一個(gè)特化流,而不是Stream<T>

int calories = menu.stream()                      //返回一個(gè)Stream<dish>
 .mapToInt(Dish::getCalories)
 .sum(); 
````VUE
最后編輯于
?著作權(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)容

  • 篩選和切片 映射 查找和匹配 規(guī)約 數(shù)值流 構(gòu)建流 歡迎訪問(wèn)本人博客:http://wangnan.tech 篩選...
    GhostStories閱讀 1,009評(píng)論 0 3
  • 流是Java API的新成員,它允許你以聲明性方式處理數(shù)據(jù)集合流操作有兩個(gè)重要的特點(diǎn):流水線——很多流操作本身會(huì)返...
    海拉魯大刷子閱讀 372評(píng)論 0 0
  • 原文地址: 深藍(lán)至尊 一. 流式處理簡(jiǎn)介 在我接觸到j(luò)ava8流式處理的時(shí)候,我的第一感覺(jué)是流式處理讓集合操作變得...
    咻咻咻i閱讀 1,271評(píng)論 0 0
  • 流的操作 流的使用一般包括三件事: 一個(gè)數(shù)據(jù)源來(lái)執(zhí)行一個(gè)查詢(xún); 一個(gè)中間操作鏈,形成一條流的流水線; 一個(gè)終端操作...
    羅志贇閱讀 1,161評(píng)論 0 50
  • 概要 流讓你從外部迭代轉(zhuǎn)向內(nèi)部迭代。這樣,你就用不著寫(xiě)下面這樣的代碼來(lái)顯式地管理數(shù)據(jù)集合的迭代(外部迭代)了: 現(xiàn)...
    潯它芉咟渡閱讀 1,629評(píng)論 1 2

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