java8新特性stream深入解析

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

繼續java8源碼的發燒熱,越看越是有充實的感覺。

數據時代下的產物

Java順應時代的發展推出的高效處理大量數據能力的api,它專注于對集合對象進行各種非常便利、高效的聚合操作,借助于同樣新出現的 Lambda 表達式,極大的提高編程效率和程序可讀性。同時它提供串行和并行兩種模式進行匯聚操作,并發模式能夠充分利用多核處理器的優勢,可以很方便地寫出高性能的并發程序。

Stream可以極大提高Java程序員的生產力,讓程序員寫出高效率、干凈、簡潔的代碼。

核心概念理解

一個流的操作 = 創建流 + 中間操作 + 結果轉換。

  1. 創建流:指從集合轉換過濾,數值轉換過濾、I/O轉換、創建等等;
  2. 中間操作:指對流中的數據進行聚合,如filter\map\sorted\reduce、distinct等等;
  3. 結果轉換:指將流進行輸出,打印、轉換成array、轉換成collection等;

Stream重要點:

  1. 流是不存儲值的,只是一個管道過程
  2. 單個流只能被使用一次,再次被使用報錯
  3. 流是支持函數式調用

測試樣例定義

static List<ICar> cars = new ArrayList<>();static Map<Integer,String> kv = new HashMap<>();public static void init(){for(int i = 1; i <= 10; i++){WeiLaiCar car = new WeiLaiCar();car.setCarWheel(i);cars.add(car);kv.put(i,i+"-value");}
}

源碼深度

java.util.stream

在java.util.stream目錄下可以看出有多種stream可以使用。Stream是支持泛型的對象的流,另外還提供了double\int\long常用數據類型的流,但他們提供的方法基本類似。

1、流是管道內部單向不可逆操作

Random random = new Random();
IntStream intStream = random.ints(10);
intStream.limit(6).forEach(PrintUtil::printTest);
intStream.toArray();

這里的第二個intStream.toArray()執行會報錯誤:IllegalStateException: stream has already been operated upon or closed,流創建流到結束流單個管道內只能順序一次使用,想要再次使用就得從源頭重新創建流重新開始;

Random random = new Random();
IntStream intStream = random.ints(10);
intStream.limit(6).forEach(PrintUtil::printTest);
random.ints(15).toArray();

2、Stream的串行和并行

流的計算提供了兩種模式:串行流和并行流,認是創建串行流。

  • 提供流方法parallel()和sequential()在串并流間相互轉換。
  • 在Collection接口上添加了兩個方法stream()\parallelStream(),parallel是并行計算的。這兩個方法的內部實現皆是通過StreamSupport.stream(xx,aa)來實現,該方法的aa參數是boolean代表是否開啟并行流;

3、collection與stream轉換

流提供有方法toArray()轉換成數組,也提供了方法collect()轉換為list\set\Collection集合;同時Arrays.stream()方法可以把數組轉換為流。

//list -> stream
Stream<ICar> carStream = cars.parallelStream();
carStream.filter(a -> a.getWheelCount() > 5).map(a-> a.hashCode()+"|"+a.getWheelCount()).forEach(PrintUtil::printTest);
//list轉換為并發stream并打印符合條件的對象的hashcode和wheel數量:730140433|8//stream -> list
Stream<ICar> tmp = cars.stream();
List<ICar> carList = tmp.collect(Collectors.toList());
carList.forEach(PrintUtil::printTest);
//通過collect方法把stream轉換為list并打印對象全稱:com.ts.util.optional.WeiLaiCar@4e515669//array -> stream
ICar[] carss = {new WeiLaiCar(1),new WeiLaiCar(2)};
Arrays.stream(carss).filter(a -> a.getWheelCount() >2).forEach(PrintUtil::printTest);
//最終輸出8個wheel大于2個的對象,并打印對象全稱:com.ts.util.optional.WeiLaiCar@4dcbadb4//stream -> array
Object[] tmps = cars.stream().filter(a ->a.getWheelCount()>7).toArray();
PrintUtil.printTest(tmps.length);
//從cars中轉換stream選出wheel大于7個的,轉換為數值最終輸出數量為:3

4、stream的排序

默認的排序要求排序對象是自然的有些值,一般dubble\int\long等;其他的類型需要主動定義comparator接口比較邏輯。

//默認sorted()要求是值natural order,即是自然順序的
cars.stream().map(a->a.getWheelCount()).sorted().forEach(PrintUtil::printTest);
//先將對象的int類型的wheel聚合成集合,再使用默認排序(順序)進行打印:1 2 3 4 5 6 ...10//自定義comparator,也可以在對象之間實現Comparator接口
cars.stream().sorted(Comparator.comparingInt(ICar::getWheelCount)).map(a->a.getWheelCount()).forEach(PrintUtil::printTest);
//自定義使用ICar的int類型wheel字段順序比較,之后再將對象的wheel字段聚合進行打印:1 2 3 4 5 6 ...10
cars.stream().sorted(Comparator.comparingInt(ICar::getWheelCount).reversed()).map(a->a.getWheelCount()).forEach(PrintUtil::printTest);
//自定義使用ICar的int類型wheel字段順序比較后再逆轉,之后再將對象的wheel字段聚合進行打印
//與上面的順序正好相反:10 9 8 7 ... 1

流包下重要的工具類

  1. Collectors 提供了很多 reduction 操作,都是靜態的方法,如聚合成集合或者其他類型,官網例子如下:
// Accumulate names into a List
List<String> list = people.stream().map(Person::getName).collect(Collectors.toList());// Accumulate names into a TreeSet
Set<String> set = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new));// Convert elements to strings and concatenate them, separated by commas
String joined = things.stream().map(Object::toString).collect(Collectors.joining(", "));// Compute sum of salaries of employee
int total = employees.stream().collect(Collectors.summingInt(Employee::getSalary)));// Group employees by department
Map<Department, List<Employee>> byDept = employees.stream().collect(Collectors.groupingBy(Employee::getDepartment));// Compute sum of salaries by department
Map<Department, Integer> totalByDept = employees.stream().collect(Collectors.groupingBy(Employee::getDepartment,Collectors.summingInt(Employee::getSalary)));// Partition students into passing and failing
Map<Boolean, List<Student>> passingFailing = students.stream().collect(Collectors.partitioningBy(s -> s.getGrade() >= PASS_THRESHOLD));
  1. StreamSupport 是stream的底層創建操作方法實現類,讓我們查看一下Stream類的部分方法源碼:
    /*** Returns an empty sequential {@code Stream}.** @param <T> the type of stream elements* @return an empty sequential stream*/public static<T> Stream<T> empty() {return StreamSupport.stream(Spliterators.<T>emptySpliterator(), false);}/*** Returns a sequential {@code Stream} containing a single element.** @param t the single element* @param <T> the type of stream elements* @return a singleton sequential stream*/public static<T> Stream<T> of(T t) {return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);}
  1. 其他創建stream的方式,通過Stream的靜態方法或者StreamSupport類:
Stream<String> stringStream = Stream.of("1","a","c");
stringStream.forEach(PrintUtil::printTest);
// 1 a cStream<Integer> integerStream = Stream.empty();
PrintUtil.printTest("count is " + integerStream.count());
//count is 0double[] tm = {22D,1.11D,33D,20.12D,11.02D,9.34D};
DoubleStream doubleStream = StreamSupport.doubleStream(Spliterators.spliterator(tm,0,5,1),true);
doubleStream.filter(a -> a < 20).forEach(PrintUtil::printTest);
//1.11 11.02

要主動擁抱新技術的出現

看著公司年輕的工程師一個比一個年輕,我變的更加努力了。要鞭策自己在項目中多嘗試使用新API各種類和方法以鍛煉自己,這些東西就是需要多用你才能發現區別并提升你的技術能力。

就算是寫業務的也能寫出不一樣的水平。時常告訴自己去學習,追求進步不要做茫茫的小白。 對于一個工程師來說學習能力是你在這個行業必備的能力。

測試用例地址:play-java-sample


作者:Owen Jia

歡迎關注他的博客:Owen Blog

堅持寫博客成了我的一種寄托

轉載于:https://my.oschina.net/timestorm/blog/3009416

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/275902.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/275902.shtml
英文地址,請注明出處:http://en.pswp.cn/news/275902.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

mysql內連接的自連接_mysql 內連接、外連接、自連接

一)內連接(等值連接)&#xff1a;查詢客戶姓名&#xff0c;訂單編號&#xff0c;訂單價格---------------------------------------------------select c.name,o.isbn,o.pricefrom customers c inner join orders owhere c.id o.customers_id;-------------------------------…

關于ASP.NET MVC

我是否要學習一下ASP.NET MVC呢&#xff1f;因爲從它剛發布的時候就已經初步的學習了一下&#xff0c;可是一直沒有堅持下來。不過心里對于這份惦記&#xff0c;又讓我始終放不下&#xff0c;看來應該抽個時間來系統的學習一下。 就這樣吧&#xff0c;把自己的博客當成微博來使…

版式設計與創意 pdf_戀愛與版式

版式設計與創意 pdfSince its beginnings, Libe?ration has been characterized by a very distinctive use of typeface, to such an extent that Libe? has put its mark on fonts from across different eras, appropriating these in a certain way.小號因斯它的起點&…

移動網站開發——標記語言

移動互聯網被稱為“第五次科技革命”&#xff0c;而隨著iPhone和Android等智能手機的日漸流行和iPad等平板電腦的出現&#xff0c;移動互聯網的潛力和趨勢也愈發顯現&#xff0c;針對移動設備的網站開發越來越受到關注&#xff0c;國內很多公司也開始重視面向所有移動設備的網站…

mysql適配器_MySQL適配器PyMySQL詳解

import pymysqlimport datainfoimport time#獲取參數host datainfo.hostusername datainfo.usernamepassword datainfo.passworddatabase datainfo.dbprint()#測試數據庫連接def testconnect():#打開數據庫鏈接db pymysql.connect(host,username,password,database)#使用c…

獲取當前Tomcat實例的端口

有時需要在當前代碼中獲取當前Server實例的端口號, 通過HttpServletRequest請求可以, 但有時也需要在沒有請求的情況下獲取到端口號. 用以下方法是可以獲取到的: public int getHttpPort() {try {MBeanServer server;if (MBeanServerFactory.findMBeanServer(null).size() >…

前端技術未來三年前瞻性思考

大家好&#xff0c;我是若川。今天推薦云謙大佬的一篇好文章&#xff0c;值得收藏。點擊下方卡片關注我、加個星標&#xff0c;或者查看源碼等系列文章。學習源碼整體架構系列、年度總結、JS基礎系列習慣從業務場景、用戶體驗、研發速度、維護成本四個維度來看框架等前端技術&a…

微信臨時素材接口_在接口中表達臨時性

微信臨時素材接口When interacting with today’s graphic user interfaces (GUI), we experience a sense of realism. As of now, certain aspects of realism (for example animations) create the appearance that user interface graphics behave in accordance with the …

程序員,當你寫程序寫累了怎么辦。

記得泡泡網的CEO李想說過這樣一句話&#xff0c;大體就是&#xff1a;做一件事情&#xff0c;一開始是興趣使然&#xff0c;然而當三分鐘熱度過去之后&#xff0c;就要靠毅力支撐自己來完成它。至少我到現在是能非常深刻的體會這句話。一開始再怎么喜歡做一件事&#xff0c;要想…

mysql 導致iis 假死_解決IIS無響應假死狀態

1 查看服務器iis的w3wp.exe對應的應用程序池在IIS6下&#xff0c;經常出現w3wp的內存占用不能及時釋放&#xff0c;從而導致服務器響應速度很慢。今天研究了一下&#xff0c;可以做以下配置&#xff1a;1、在IIS中對每個網站進行單獨的應用程序池配置。即互相之間不影響。2、設…

Swift 5將強制執行內存獨占訪問

Swift 5將帶來改進的Swift程序內存安全性&#xff0c;在程序的其他部分修改變量時&#xff0c;不允許通過其他變量名來訪問這些變量。這個變更對現有應用程序的行為和Swift編譯器本身都有重要影響。Swift 5將帶來改進的Swift程序內存安全性&#xff0c;在程序的其他部分修改變量…

GitHub 支持上傳視頻文件啦!

大家好&#xff0c;我是若川。今天周六&#xff0c;分享一篇熱點新聞。文章較短&#xff0c;預計5分鐘可看完。近日 Github 宣布支持了視頻上傳功能&#xff0c;意味著&#xff0c;大家在提 issue 時可以攜帶視頻了&#xff0c;這極大地提高了開發者和維護者的效率&#xff0c;…

ui設計 網絡錯誤_UI設計人員常犯的10個錯誤

ui設計 網絡錯誤重點 (Top highlight)1.不考慮范圍 (1. Disregarding scope)It’s not uncommon for designers to introduce features that will overcomplicate the development process while bringing no additional value to the application. Focusing on the business o…

灰色的生命

也許幸福從來沒有在我身邊也許是已經在我身邊但我抓不住,摸不著 你的出現讓我驚奇為我灰色的生命添上了從沒見過的色彩我不相信這一切都是我的 不相信總是害怕相信了之后卻要面對殘酷的現實 但為何你讓我相信所有抓住了希望卻又轉過身沒有離去但讓一切停止望著你不想說…

小程序 node.js mysql_基于Node.js+MySQL開發的開源微信小程序B2C商城(頁面高仿網易嚴選)...

高仿網易嚴選的微信小程序商城(微信小程序客戶端)界面高仿網易嚴選商城(主要是2016年wap版)測試數據采集自網易嚴選商城功能和數據庫參考ecshop服務端api基于&#xff2e;ode.jsThinkJSMySQL計劃添加基于Vue.js的后臺管理系統、PC版、&#xff37;ap版項目截圖功能列表首頁分類…

前端菜鳥筆記 Day-5 CSS 高級

文章大綱來源&#xff1a;【Day 5】CSS 高級 CSS 選擇器CSS 拓展CSS 單位CSS 參考手冊CSS 選擇器 內容引用&#xff1a;CSS 選擇器 元素選擇器 html { ... } 復制代碼選擇器分組 h2, p { ... } 復制代碼類選擇器 .important { ... } p.warning { ... } .important.warning { .…

推薦幾個干貨超多助你成長的前端大佬

不得不說&#xff0c;如今比前些年學習資料多很多了。現在的前端公眾號也挺多的&#xff0c;這里推薦幾個前端大佬運營的公眾號&#xff0c;都是聚焦前端垂直領域的優質公眾號&#xff0c;關注這些公眾號至少可以&#xff1a;1、了解現在前端技術發展情況和未來發展趨勢&#x…

背景圖片_背景

背景圖片A designer’s journey is one that’s littered with many portfolios. Many of which have been reduced to a mere 404 error page, an abandoned link or another archive in the folders. Recently, while updating my portfolio, all the forgotten versions tha…

解決《Mobile繪制背景圖片》中的問題

與PC平臺的開發相比&#xff0c;Mobile的開發麻煩了許多&#xff0c;至少這是我的感覺 。 謝謝&#xff0d;&#xff0d;“ Fly Pig(^^)” 的文章《Mobile開發(繪制背景圖片) 》 http://www.cnblogs.com/Bright-Liang/archive/2009/06/11/1501309.html 不過對于我這種低手來說&…

mysql 5.6.31 winx64_詳解介紹MySQL5.6.31winx64.zip安裝配置的圖文教程

這篇文章主要介紹了MySQL5.6.31 winx64.zip 安裝配置教程詳解,非常不錯&#xff0c;具有參考借鑒價值&#xff0c;需要的朋友可以參考下#1. 下載##2.解壓到本地 修改必要配置my*.ini#3.mysql installadmin模式啟動cmdcd mysql目錄/bin執行安裝&#xff1a; mysqld -install啟動…