[轉載] Java8-Stream API 詳解

參考鏈接: 如何在Java 8中從Stream獲取ArrayList

摘要?

?Stream 作為 Java 8 的一大亮點,它與 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。它也不同于 StAX 對 XML 解析的 Stream,也不是 Amazon Kinesis 對大數據實時處理的 Stream。Java 8 中的 Stream 是對集合(Collection)對象功能的增強,它專注于對集合對象進行各種非常便利、高效的聚合操作(aggregate operation),或者大批量數據操作 (bulk data operation)。Stream API 借助于同樣新出現的 Lambda 表達式,極大的提高編程效率和程序可讀性。同時它提供串行和并行兩種模式進行匯聚操作,并發模式能夠充分利用多核處理器的優勢,使用 fork/join 并行方式來拆分任務和加速處理過程。通常編寫并行代碼很難而且容易出錯, 但使用 Stream API 無需編寫一行多線程的代碼,就可以很方便地寫出高性能的并發程序。所以說,Java 8 中首次出現的 java.util.stream 是一個函數式語言+多核時代綜合影響的產物。?

簡介?

流(Stream)是數據通道,用于操作數據源(集合,數組等)所生成的元素序列 “集合講的的是數據,流講的是計算” 注意: ?① Stream不會存儲元素 ?② Stream不會改變源對象,相反他們會返回一個持有結果的新的Stream ?③ Stream操作是延遲執行的,這意味著他們等到需要結果的時候才會執行(惰性求值)?

Stream操作的三個步驟?

創建Stream 一個數據源(如:集合,數組)獲取一個流中間操作 一個中間操作鏈,對數據源的數據進行處理終止操作(終端操作) 一個終止操作,執行中間操作鏈,并產生結果??

一:創建Stream?

Collection提供了兩個方法.stream()與paralleStream()?

@org.junit.Test

public void test4(){

? ? List<Integer> list = new ArrayList<>();

? ? Stream<Integer> stream = list.stream();//串行流

? ? Stream<Integer> integerStream = list.parallelStream();//并行流

}

?

通過Arrays中的Stream()獲取一個數組流。?

?Integer[] integers ={};

?Stream<Integer> stream1 = Arrays.stream(integers);

?

通過Stream類中靜態方法of()?

Stream<String> stream2 = Stream.of("aaa", "bbb");

?

創建無限流(無窮的數據)?

? 生成 //通過生成器產生5個10以內的隨機數,如果不使用limit就會無限生成10以內隨機數

Stream.generate(() -> Math.random() * 10).limit(5).forEach(System.out::println);

----------輸出--------

0.8320556195819129

6.260534125204207

7.344094646332503

0.18490598959698068

6.392272744710005

?

? 迭代 //通過迭代的方式(一元運算)生成5個數

Stream.iterate(0,x->x+2).limit(5).forEach(System.out::println);

-------------------輸出------------

0

2

4

6

8

??

二:中間操作?

?

?多個中間操作可以連接起來形成一個流水線,除非流水線上觸發終止操作,否則中間操作不會執行任何的處理,而在終止操作時一次性全部執行,稱為“惰性求值”?

?List<Integer> list = Arrays.asList(1,2,3,523,21,55);

Stream<Integer> stream3 = list.stream().filter(x -> {

? ? ? ? ?System.out.println("函數執行");

? ? ? ? ?return x > 10;

?// stream3.forEach(System.out::println);

?

?上面的代碼沒有終止操作,當你運行時不會打印任何東西?

?

①篩選與切片?

filter----接收Lambda,從流中排除某些元素?

//filter()中需要使用斷言型接口(Predicate)

List<Integer> list = Arrays.asList(1,2,3,523,21,55);

Stream<Integer> stream3 = list.stream().filter(x -> x > 10);

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

?

limit----截斷流,使其元素不超過給定數量?

List<Integer> list = Arrays.asList(1,2,3,523,21,55);

Stream<Integer> stream3 = list.stream().limit(3);

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

--------------------輸出---------------------

1

2

3

?

skip----跳過元素返回一個拋棄了前n個元素的流,若流中元素不滿足n個,則返回一個空流,與limit形成互補?

List<Integer> list = Arrays.asList(1,2,3,523,21,55);

Stream<Integer> stream3 = list.stream().skip(3);

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

--------------------輸出---------------------

523

21

55

?

distinct----篩選,通過流所所生成元素的hashCode()和equals()去除重復元素?

? List<Integer> list = Arrays.asList(1,2,3,3,2,4);

? Stream<Integer> stream3 = list.stream().distinct();

? stream3.forEach(System.out::println);

? --------------------輸出---------------------

? 1

? 2

? 3

? 4

?

注意:自定義的實體類使用distinct去重時,一定要先重寫hashCode()和equals()?

②映射?

map----接收Lambda,將元素轉換為其他形式或提取信息時,接收一個函數作為參數,該函數被應用到每個元素上,并將其映射成一個新的元素//map()里面使用函數型接口(Function)

List<String> list = Arrays.asList("aa","bb","cc");

Stream<String> stream3 = list.stream().map(String::toUpperCase);

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

----------------------輸出-----------------------

AA

BB

CC

------------------------------------------------

集合里的每一個元素都會使用到String.toUpperCase()方法

它是以aa作為一個元素,bb作為一個元素?

?flatMap----接收一個函數作為參數,將流中的每個值都換成另一個流,然后把所有流連接一個流List<String> list = Arrays.asList("aa","bb","cc");

? ? ? ?Stream<String> stream3 = list.stream().flatMap(l -> {

? ? ? ? ? ?String[] strings = l.split("");

? ? ? ? ? ?return Arrays.stream(strings);

? ? ? ?});

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

-------------------輸出-----------

a

a

b

b

c

c

-----------------------------------------------

flatMap將原來的流轉換為一個新的流并且,是以每一個值為單位的

?

? ?

? ??

? ??

③排序?

sorted() 自然排序 按照Comparable的方式List<String> list = Arrays.asList("aa","cc","bb");

Stream<String> stream3 = list.stream().sorted();

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

---------------輸出-----------

aa

bb

cc

?sorted( Comparator com)定制排序 List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

?Stream<Integer> stream3 = list.stream().sorted(Integer::compare);

?stream3.forEach(System.out::println);

?--------------輸出--------------

?1

?2

?3

?3

?6

?8

?9

??

終止操作?

①查找與匹配?

allMatch----檢查是否匹配所有元素//allMatch()里面的時斷言型接口(Predicate)

?List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

?boolean b = list.stream().allMatch(x -> x > 3);

?System.out.println(b);

?------------------輸出--------------------

?false

?//因為不是所有的數都大于3

?anyMatch----檢查是否有匹配至少一個元素//anyMatch()里面的時斷言型接口(Predicate)

?List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

?boolean b = list.stream().anyMatch(x -> x > 3);

?System.out.println(b);

? ------------------輸出--------------------

?true

?//只要有大于3的數就返回true

?noneMatch----檢查是否沒有匹配的元素//noneMatch()里面的時斷言型接口(Predicate)

List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

boolean b = list.stream().noneMatch(x -> x > 3);

System.out.println(b);

?------------------輸出--------------------

?false

?//雙重否定,返回false就是有匹配的元素

?findFirst----返回第一個元素List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

Optional<Integer> first = list.stream().findFirst();

System.out.println(first.get());

-----------------輸出----------------

1

?findAny----返回當前流中的任意一元素List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

Optional<Integer> first = list.stream().findAny();

System.out.println(first.get());

-----------------輸出----------------

1

?count-----返回流中元素的總數List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

long count = list.stream().count();

System.out.println(count);

-----------------輸出----------------

7

?max----返回流中最大值 List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

?Optional<Integer> max = list.stream().max(Integer::compareTo);

?System.out.println(max.get());

?-----------------輸出----------------

9

?min----返回流中的最小值List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

Optional<Integer> min = list.stream().min(Integer::compareTo);

System.out.println(min.get());

?-----------------輸出----------------

1

?forEach----遍歷流中的元素 List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

?list.stream().forEach(System.out::println);

?-----------------輸出----------------

1

3

2

6

8

3

9

//注意:forEach的迭代操作是由Stream API完成的稱為內部迭代

//借助于iterator的方式為外部迭代

??

②歸約?

reduce(T identity,BinaryOperator)—可以將流中元素反復結合起來得到一個值,返回T List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

?Integer reduce = list.stream().reduce(0, (x, y) -> x + y);

?System.out.println(reduce);

?-----------------輸出----------------

?32

?//根據2元運算將所有的數加起來

?//首先以0為x,1為y,結果為1,然后1為x,取3為y,結果為4,以4為x...以此類推

?reduce(BinaryOpreator)----可以將流中元素反復結合起來,返回Optional< T > List<Integer> list = Arrays.asList(1,3,2,6,8,3,9);

?Optional<Integer> reduce = list.stream().reduce((x, y) -> x + y);

?System.out.println(reduce.get());

? -----------------輸出----------------

?32

?//原理同上,只是這里沒有初始值,直接取1為x

?//所以ist就有可能為空,當返回的值可能為空時,結果存儲在Optional容器中,避免空指針異常

??

③收集?

collect----將流轉換為其他形式,接收一個Collector接口的實現,用于給Stream中元素做匯總的方法?

?

?Colloector 接口中方法的實現決定了如何對流執行手機操作(如收集到List、Set、Map中)但是Collectots實用類提供了很多靜態方法,可以方便的創建常見收集器實例?

?

接下來進行詳細介紹 首先創建一個實體類?

public class User {

? ? private String name;

? ? private Integer age;

? ? private double salary;

?

? ? public User(String name, Integer age, double salary) {

? ? ? ? this.name = name;

? ? ? ? this.age = age;

? ? ? ? this.salary = salary;

? ? }

?

? ? public String getName() {

? ? ? ? return name;

? ? }

?

? ? public void setName(String name) {

? ? ? ? this.name = name;

? ? }

?

? ? public Integer getAge() {

? ? ? ? return age;

? ? }

?

? ? public void setAge(Integer age) {

? ? ? ? this.age = age;

? ? }

?

? ? public double getSalary() {

? ? ? ? return salary;

? ? }

?

? ? public void setSalary(double salary) {

? ? ? ? this.salary = salary;

? ? }

?

? ? @Override

? ? public String toString() {

? ? ? ? return "User{" +

? ? ? ? ? ? ? ? "name='" + name + '\'' +

? ? ? ? ? ? ? ? ", age=" + age +

? ? ? ? ? ? ? ? ", salary=" + salary +

? ? ? ? ? ? ? ? '}';

? ? }

?

? ? @Override

? ? public boolean equals(Object o) {

? ? ? ? if (this == o) return true;

? ? ? ? if (o == null || getClass() != o.getClass()) return false;

? ? ? ? User user = (User) o;

? ? ? ? return Double.compare(user.salary, salary) == 0 &&

? ? ? ? ? ? ? ? Objects.equals(name, user.name) &&

? ? ? ? ? ? ? ? Objects.equals(age, user.age);

? ? }

?

? ? @Override

? ? public int hashCode() {

? ? ? ? return Objects.hash(name, age, salary);

? ? }

}

?

在測試類中準備好數據?

public class StreamTest {

? ? ?List<User> user = Arrays.asList(new User("張三",12,1000.00),

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? new User ("李四",32,4000),

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? new User ("王五",40,4000),

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? new User ("王五",40,4000));

}

?

根據名稱生成一個新的List?

?List<String> list = user.stream().map(User::getName).collect(Collectors.toList());

?list.forEach(System.out::println);

?-----------------輸出--------------

?張三

?李四

?王五

?王五

?

根據名稱生成一個新的Set?

?Set<String> set = user.stream().map(User::getName).collect(Collectors.toSet());

?set.forEach(System.out::println);

?-----------------輸出--------------

?張三

?李四

?王五

?

根據名稱生成一個新的HashSet?

?HashSet<String> hashSet = user.stream().map(User::getName).collect(Collectors.toCollection(HashSet::new));

?hashSet.forEach(System.out::println);

?-----------------輸出--------------

?李四

?張三

?王五

?

獲取流中的元素總數?

Long count = user.stream().collect(Collectors.counting());

System.out.println(count);

-----------------輸出--------------

4

?

根據工資獲取平均值?

Double avg = user.stream().collect(Collectors.averagingDouble(User::getSalary));

System.out.println(avg);

-----------------輸出--------------

3250.0

?

根據工資獲取總和?

Double sum = user.stream().collect(Collectors.summingDouble(User::getSalary));

System.out.println(sum);

-----------------輸出--------------

13000.0

?

根據工資獲取組函數?

?DoubleSummaryStatistics sum = user.stream().collect(Collectors.summarizingDouble(User::getSalary));

?System.out.println(sum);

?-----------------輸出--------------

?DoubleSummaryStatistics{count=4, sum=13000.000000, min=1000.000000, average=3250.000000, max=4000.000000}

?

根據工資獲取最大值?

?Optional<User> max = user.stream().collect(Collectors.maxBy(Comparator.comparingDouble(User::getSalary)));

?System.out.println(max.get());

?-----------------輸出--------------

?User{name='李四', age=32, salary=4000.0}

?

根據工資獲取最小值?

?Optional<User> min = user.stream().collect(Collectors.minBy(Comparator.comparingDouble(User::getSalary)));

?System.out.println(min.get());

?-----------------輸出--------------

?User{name='張三', age=12, salary=1000.0}

?

分組?

Map<Double, List<User>> map = user.stream().collect(Collectors.groupingBy(User::getSalary));

System.out.println(map);

-----------------輸出--------------

{4000.0=[User{name='李四', age=32, salary=4000.0}, User{name='王五', age=40, salary=4000.0}, User{name='王五', age=40, salary=4000.0}], 1000.0=[User{name='張三', age=12, salary=1000.0}]}

?

多級分組?

Map<Double, Map<String, List<User>>> collect = user.stream().collect(Collectors.groupingBy(User::getSalary, Collectors.groupingBy(

? ? ? ? ? ? ? ? u -> {

? ? ? ? ? ? ? ? ? ? if ( u.getAge() <= 12) {

? ? ? ? ? ? ? ? ? ? ? ? return "青年";

? ? ? ? ? ? ? ? ? ? } else if ( u.getAge() <= 32) {

? ? ? ? ? ? ? ? ? ? ? ? return "中年";

? ? ? ? ? ? ? ? ? ? } else {

? ? ? ? ? ? ? ? ? ? ? ? return "老年";

? ? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ? }

? ? ? ? )));

System.out.println(collect);? ??

-----------------輸出--------------? ??

{4000.0={老年=[User{name='王五', age=40, salary=4000.0}, User{name='王五', age=40, salary=4000.0}], 中年=[User{name='李四', age=32, salary=4000.0}]}, 1000.0={青年=[User{name='張三', age=12, salary=1000.0}]}}

?

分區?

Map<Boolean, List<User>> collect1 = user.stream().collect(Collectors.partitioningBy(e -> e.getSalary() > 3000));

System.out.println(collect1);

-----------------輸出--------------? ?

{false=[User{name='張三', age=12, salary=1000.0}], true=[User{name='李四', age=32, salary=4000.0}, User{name='王五', age=40, salary=4000.0}, User{name='王五', age=40, salary=4000.0}]}

?

連接?

String s = user.stream().map(User::getName).collect(Collectors.joining("--"));

System.out.println(s);

-----------------輸出--------------

張三--李四--王五--王五

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

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

相關文章

在Microsoft System Center中利用您的現有投資管理VMware--Veeam MP v6.5

在 Microsoft System Center 中利用您的現有投資管理 VMware VeeamManagement Pack (MP) v6.5 適用于物理、虛擬和備份基礎架構的單一的虛擬管理平臺 前段時間介紹了Veeam Management Pack (MP) v6.0產品&#xff0c;昨天發布了新版本VeeamManagement Pack (MP) v6.5&#xff0…

[轉載] Java關鍵字(Java 8版本)

參考鏈接&#xff1a; 所有Java關鍵字列表 定義 被Java語言賦予了特殊含義&#xff0c;用作專門用途的字符串&#xff08;單詞&#xff09;&#xff0c;這些關鍵字不能用于常量、變量、和任何標識符的名稱。 Java關鍵字(Java 8版本) Java關鍵字(Java 8 以后版本) 注意事…

uiw 1.2.17 發布,基于 React 16 的組件庫

發布&#xff0c; 高品質的UI工具包&#xff0c;React 16的組件庫。 文檔網站&#xff1a;uiw-react.github.io開源倉庫&#xff1a;github.com/uiw-react/u… 更新內容&#xff1a; ? 修復沒有代碼檢測文件匹配*.css。 5712887 ? 添加 .editorconfig 文件. d82dabf ? 給測試…

[轉載] Java中this和super關鍵字分別是什么意思

參考鏈接&#xff1a; Java中的Super關鍵字 this和super關鍵字 this是自身的一個對象&#xff0c;代表對象本身可以理解為指代當前的對象&#xff0c;它可以調用當前對象的屬性、方法和構造方法&#xff0c;一般情況下可以省略&#xff0c;必須使用this的地方是區分出現名字重…

SpringMVC注解HelloWorld

今天整理一下SpringMVC注解 歡迎拍磚 RequestMapping RequestMapping是一個用來處理請求地址映射的注解&#xff0c;可用于類或方法上。用于類上&#xff0c;表示類中的所有響應請求的方法都是以該地址作為父路徑。 RequestMapping注解有六個屬性&#xff0c;下面我們把她分成三…

mysql問答匯集

問:A&#xff0c;B兩臺mysql實現主從復制,A提供寫&#xff0c;B提供讀,那既然B要同步A&#xff0c;當A更新數據的時候&#xff0c;B不也一樣要更新嗎&#xff1f;那B不還是沒有實現負載減輕嗎&#xff1f;還有能通過MYSQL proxy實現3臺mysq均衡l嗎&#xff1f;一臺寫&#xff0…

自制 移動端 純原生 Slider滑動插件

在Google搜關鍵字“slider”或“swiper”能找到一大堆相關插件&#xff0c;自己造輪子是為了能更好的理解其中的原理。 給這個插件取名為“veSlider”是指“very easy slider”非常簡單的一個滑動插件。 這只是個半成品&#xff0c;僅僅實現了手指滑動、自動輪播、跳轉等基本功…

ISA Server 2006 部署步驟

ISA Server 2006 部署步驟 Posted by 尹揆 在這里先把ISA2006的安裝步驟給大家貼出來,后面陸續會有一些配置及日常的應用,希望大家多多指教!呵呵.ISA功能的強大自然不用多說了,一句話只要能想到它就能做到!放入光盤出現在我們面前還是其人性化的界面點默認的下一步吧接受協議序…

ELK 分析 nginx access 日志

注意&#xff1a;修改配置后建議重新創建index 1、nginx 日志文件格式 123log_format elk "$http_clientip | $http_x_forwarded_for | $time_local | $request | $status | $body_bytes_sent | ""$request_body | $content_length | $http_referer | $http_use…

mysql將查詢數據另存

1.查詢mysql的存儲執行目錄&#xff08;secure-file-priv是指定文件夾作為導出文件存放的地方&#xff09;所以需要查詢以下&#xff0c;不然會報1290錯誤 show variables like %secure%;2.查詢并轉存 SELECT * into outfile C:\ProgramData\MySQL\MySQL Server 5.7\Uploads\zo…

重新撿起flask(三)

記一次bug調試。 本來以為模板這一章可以很快的過掉的&#xff0c;剛剛寫完的2其實只剩下個flask-moment時間庫了&#xff0c;之前早就做過&#xff0c;記得很簡單&#xff0c;本來說只要敲一下代碼就結束&#xff0c;沒想到&#xff0c;踩坑里去了。 調試bug嗎&#xff0c;我想…

遠程服務器部署spring boot 項目(centos7為例)

1.打包項目&#xff08;可以是jar包&#xff0c;也可以是war包&#xff09;以jar包為例&#xff08;用eclipse打包&#xff09;&#xff1a;1.項目目錄右擊--debug as&#xff08;run as&#xff09;--maven build&#xff0c;然后輸入package&#xff0c;點擊debug&#xff0c…

SIN的服務器配置

統計了新加坡服務器中IBM XIV存儲掛載的主機列表。 對于vmware虛擬機來說&#xff0c;是這么組成的&#xff1a; 存儲分了多個lun&#xff0c;在os側叫做data store&#xff0c;多個datastore掛給多個物理機&#xff0c;物理機(安裝了esxi軟件)稱為ESXI主機&#xff0c;多個ESX…

sklearn的train_test_split

sklearn的train_test_split train_test_split函數用于將矩陣隨機劃分為訓練子集和測試子集&#xff0c;并返回劃分好的訓練集測試集樣本和訓練集測試集標簽。 格式&#xff1a; X_train,X_test, y_train, y_test cross_validation.train_test_split(train_data,train_target,…

textmate bundle for jquery

使用這個bundle的例子:鍵入ready然后按tab就會生成下面的代碼:$(document).ready(function() { }); 其中第二行被選中,這時在里面編寫jquery代碼即可. 如果要查看某個function的官方文檔的話可以在鍵入的function之后使用快捷鍵ctrlh 查看. 關于bundle的下載 這里是一個textmat…

sklearn機器學習實例

原創網址&#xff1a;https://blog.csdn.net/qq_27150893/article/details/80169736 sklearn是非常流行的機器學習庫&#xff0c;實現了很多的機器學習模型。官網&#xff1a;http://scikit-learn.org/stable/ 里面有全面的實例和模型參數講解&#xff0c;用到哪個模型就去官…

CSVDE批量導入域用戶

CSVDE批量導入用戶 你可以使用Csvde格式的文件在活動目錄中創建用戶帳號和其他類型的帳號。但你不能使用Csvde刪除活動目錄中的對象。 使用Csvde命令行工具創建用戶帳號&#xff0c;采用下列步驟&#xff1a; 1. 創建Csvde輸入文件。文件應包含下列信息。 屬性行&#xff1a;這…

sklearn 實例

http://scikit-learn.org/stable/auto_examples/index.html sklearn例子大全 https://deeplearning4j.org/mnist-for-beginners deeplearning官網

pip 安裝模塊時報“pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='files.pythonh”

連接鏡像網站即可 以豆瓣鏡像為例&#xff1a; 解決方案&#xff1a; pip install grpcio-tools -i https://pypi.doubanio.com/simple 后面的-i https://pypi.doubanio.com/simple即是鏡像 鏡像站推薦&#xff1a; 阿里云 http://mirrors.aliyun.com/pypi/simple/ 中國科…

【轉載】細聊冗余表數據一致性(架構師之路)

本文主要討論四個問題&#xff1a; &#xff08;1&#xff09;為什么會有冗余表的需求 &#xff08;2&#xff09;如何實現冗余表 &#xff08;3&#xff09;正反冗余表誰先執行 &#xff08;4&#xff09;冗余表如何保證數據的一致性 一、需求緣起 互聯網很多業務場景的數據量…