摘要:使用我們來看下面這段代碼,里面有一個屬性代表菜品的卡路里值,現在的需求是按卡路里對菜品進行排序再返回菜名,并且要求卡路里的值大于。
前言:
在實際開發中經常需要獲取各種各樣不同格式的數據,因為數據庫的表結構是一開始就設計好的所以很多時候我們不得不先從數據庫里或其他地方獲得數據后再根據需求去一層一層的篩選數據,在Java 8之前的做法不外乎就是各種List、Set一起上,各種循環判斷。如果只是簡單的需求還好說,循環個一兩次再判斷一下就可以解決,但是需求復雜的話就會寫出很復雜的代碼出來,時間久了后不僅自己看不懂,而且因為代碼太復雜測試的時候不敢保證覆蓋到所有的地方,萬一代碼到了線上出問題,不僅不好改還可能影響到以前的功能,而在Java 8中就提供了新的特性stream,專門用于對集合中的數據進行篩選、分類等操作,下面我們就會介紹stream的使用。
stream使用:我們來看下面這段代碼,Dish里面有一個屬性calories代表菜品的卡路里值,現在的需求是按卡路里對菜品進行排序再返回菜名,并且要求卡路里的值大于400。我們可以看到下面的操作非常繁瑣,先篩選出卡路里大于400的放入集合中,然后對這個集合進行排序,最后循環這個集合把名字放入一個新的集合,這是一個很常見的代碼,在Java 8之前都是這么寫的,但是這還只是對一個屬性的篩選、排序就這么繁瑣了,如果是多個屬性會更加麻煩,下面我們就看看用stream是怎么實現的。
//將卡路里低于400的對象都放到集合中 ListlowCaloricDishes = new ArrayList<>(); for(Dish d: menu){ if(d.getCalories() < 400){ lowCaloricDishes.add(d); } } //把這個集合排序 Collections.sort(lowCaloricDishes, new Comparator () { public int compare(Dish d1, Dish d2){ return Integer.compare(d1.getCalories(), d2.getCalories()); } }); //再新建一個String類型的集合來存放菜名 List lowCaloricDishesName = new ArrayList<>(); for(Dish d: lowCaloricDishes){ lowCaloricDishesName.add(d.getName()); }
這是Java 8中stream的用法,我們會發現這段代碼寫起來非常舒服,首先調用stream()方法獲取了集合menu的流,然后調用了filter方法來篩選出卡路里超過400的元素,接著調用了sorted方法對篩選出來的元素進行排序,再調用map方法把篩選出來的元素里面的name屬性抽出來作為一個新的流,最后一步則是調用collect方法把存放name的流轉為List格式返回,得到的結果和上面一模一樣,但是整個步驟一目了然,先做什么后做什么,非常清晰,這就是stream的用法。
import static java.util.Comparator.comparing; import static java.util.stream.Collectors.toList; Liststream的定義:menu = ... List lowCaloricDishesName = menu.stream() //篩選出卡路里大于400的 .filter(d -> d.getCalories() < 400) //按卡路里值排序 .sorted(comparing(Dish::getCalories)) //抽取名字屬性創建一個新的流 .map(Dish::getName) //這個流按List類型返回 .collect(toList());
講到這里大家可能會產生疑惑,流到底是什么,為什么它可以進行這樣的操作。簡單來說流其實就是 “從支持數據處理操作的源生成的元素序列” ,這句話到底是什么意思呢?下面我們來看看流的各種特性就明白了。
元素序列,可以通過流訪問到特定類型的一組有序的值,就像我們通過集合訪問這些數據一樣,只不過集合是為了存儲數據,而流則注重與對數據的計算和處理。
源,流可以會從一個數據源那里獲取數據并生成流,例如上面講的從集合中獲取,生成的流里面的元素和數據源里的一致。
數據處理操作,就像第一條里說的,流是注重與對數據的計算和處理,所以它有很多不同的方法可以對數據進行操作,例如篩選、分類、排序等等。
流水線,顧名思義,流的很多操作都會返回一個新的流,所以我們上面可以使用連綴的方式調用那些方法,其實每個操作都是基于它前面的那個操作返回的流進行的。
我們來看下面的這段代碼和它的流程圖。它一開始從menu這個集合中獲取到了流,流里面的數據和集合是相同的,然后調用filter方法之后篩選出符合條件的元素組成一個新的流傳遞給了map方法,然后map方法又從這個流里面把元素的名字取出來組成一個新流傳遞給limit方法,limit方法則只取了前3個組成一個流傳遞給collect方法然后返回一個List,這就是流的工作原理
Liststream只能遍歷一次:list = menu.stream() //篩選出卡路里高于300的元素 .filter(d -> d.getCalories() > 300) //獲取名字組成的流 .map(Dish::getName) //只取前3個 .limit(3) //返回List格式 .collect(toList()); System.out.println(list );
流和集合不一樣,集合可以想遍歷多少次就遍歷多少次,但是流只能遍歷一次,如果你做了下面這樣的操作,那代碼會拋出一個java.lang.IllegalStateException異常,流已被操作或關閉。
Liststream的兩種操作:title = Arrays.asList("Java8", "In", "Action"); Stream s = title.stream(); s.forEach(System.out::println); s.forEach(System.out::println);
還是繼續看這段代碼,其中filter、map和limit操作被稱為 中間操作 , 中間操作 會返回一個新的流,而collect則被稱為 終端操作 ,只有終端操作才會讓整個流執行并關閉,也就是說只有當collect被執行時filter、map和limit才會被執行,上面講到流只能遍歷一次就是因為forEach就是一個終端操作,執行完后就關閉流了。
Listlist = menu.stream() //篩選出卡路里高于300的元素 .filter(d -> d.getCalories() > 300) //獲取名字組成的流 .map(Dish::getName) //只取前3個 .limit(3) //返回List格式 .collect(toList());
以上就是stream的基本使用方法了,當然它的功能還遠遠不止這些,后面我們還會講到篩選、分組、查找等更強大的操作。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/76443.html
摘要:從發布到現在,已有三年多了,也得到了廣泛的應用,但似乎里面最重要的特性和對很多人來說還是很陌生。想通過介紹一些實際的問題和答案來講解在現實開發中我們可以通過和可以做些什么,以及什么是正確的姿勢。 從Java 8 2014 發布到現在,已有三年多了,JDK 8 也得到了廣泛的應用,但似乎Java 8里面最重要的特性:Lambdas和Stream APIs對很多人來說還是很陌生。想通過介紹...
摘要:獲取每個元素的字符串長度放入新流中,然后轉為類型。歸約歸約就是把整個流歸約成一個值的操作,比如求集合中最大的元素所有元素值的和之類的操作。 前言: 上一篇文章 Java 8之stream介紹和使用 中講解了stream的定義和用法,簡單介紹幾個最基本最常用的方法,其實stream還有更強大的功能,這篇文章就會給大家介紹stream的進階用法。 篩選: 在上一篇文章中我們介紹了使用fi...
摘要:數值流的使用想要使用數值流其實很簡單,只需要調用方法就可以獲得一個數值流了,我們會發現數值流有更多的封裝好的計算方法,更加方便我們對數值的計算。運行結果有時候我們可能會想將數值流轉換回原來的流,我們可以調用方法。 數值流: 數值流,顧名思義就是專門用來操作基礎數據類型的流,那它的作用是什么呢?先看下面的代碼。這段代碼是獲取集合每個對象的num字段的值,然后求所和。得出的結果是15,看上...
摘要:前言在前面的之介紹和使用和之進階中講了的使用方式和一些常用的方法,這篇文章就來演示一下的實際應用。實際應用先創建一個訂單類和商品類,每個訂單都有年份商品數量和商品對象屬性,而商品類里面則包含了名字和價格屬性。 前言: 在前面的 Java 8之stream介紹和使用 和 Java 8之stream進階 中講了stream的使用方式和一些常用的方法,這篇文章就來演示一下stream的實際應...
摘要:需要注意的是很多流操作本身就會返回一個流,所以多個操作可以直接連接起來,如下圖這樣,操作可以進行鏈式調用,并且并行流還可以實現數據流并行處理操作。為集合創建并行流。 上一篇文章,小樂給大家介紹了《Java8新特性之方法引用》,下面接下來小樂將會給大家介紹Java8新特性之Stream,稱之為流,本篇文章為上半部分。 1、什么是流? Java Se中對于流的操作有輸入輸出IO流,而Jav...
閱讀 1814·2021-10-09 09:44
閱讀 2690·2021-09-22 15:38
閱讀 2451·2021-09-09 09:33
閱讀 686·2021-09-07 09:58
閱讀 1785·2021-09-02 15:41
閱讀 2485·2019-08-30 15:55
閱讀 1796·2019-08-30 15:55
閱讀 533·2019-08-30 15:44