一秆剪、了解Stream
Java8中有兩大最為重要的改變赊淑。第一個是Lambda表達式;另外一個則是Stream API(java.util.stream.*)仅讽。
Stream是Java8中處理集合的關(guān)鍵抽象概念陶缺,它可以指定你希望對集合進行的操作,可以執(zhí)行非常復(fù)雜的查找洁灵、過濾和映射數(shù)據(jù)等操作饱岸。
使用Stream API對集合數(shù)據(jù)進行操作,就類似于使用sql執(zhí)行的數(shù)據(jù)庫查詢徽千。也可以使用Stream API來并行執(zhí)行操作苫费。簡而言之,Stream API提供了一種高效且易于使用的處理數(shù)據(jù)的方式罐栈。
二黍衙、什么是Stream
流(Stream)到底是什么呢?
是數(shù)據(jù)渠道荠诬,用于操作數(shù)據(jù)源(集合琅翻、數(shù)組等)所生成的元素序列。
“集合講的是數(shù)據(jù)柑贞,流講的是計算方椎!”。
注意:
(1)钧嘶、Stream自己不會存儲元素棠众。
(2)、Stream不會改變源對象有决。相反闸拿,他們會返回一個持有結(jié)果的新Stream。
(3)书幕、Stream操作是延遲執(zhí)行的新荤。這意味著他們會等到需要結(jié)果的時候才執(zhí)行。
三台汇、Stream的操作三個步驟
(1)苛骨、創(chuàng)建Stream
一個數(shù)據(jù)源(如:集合篱瞎、數(shù)組),獲取一個流
(2)痒芝、中間操作
一個中間操作鏈俐筋,對數(shù)據(jù)源的數(shù)據(jù)進行處理
(3)、終止操作(終端操作)
一個終止操作严衬,執(zhí)行中間操作鏈澄者,并產(chǎn)生結(jié)果。
四瞳步、創(chuàng)建Stream
在創(chuàng)建Stream前闷哆,我先來創(chuàng)建一個對象,供下面使用单起。Employee.java
package com.nieshenkuan.pojo;
public class Employee {
private int id;
private String name;
private int age;
private double salary;
public Employee() {
}
public Employee(String name) {
this.name = name;
}
public Employee(Integer id) {
this.id = id;
}
public Employee(Integer id,Integer age) {
this.id = id;
this.age = age;
}
public Employee(String name, int age) {
this.name = name;
this.age = age;
}
public Employee(int id, String name, int age, double salary) {
this.id = id;
this.name = name;
this.age = age;
this.salary = salary;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String show() {
return "測試方法引用抱怔!";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
long temp;
temp = Double.doubleToLongBits(salary);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee other = (Employee) obj;
if (age != other.age)
return false;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
return false;
return true;
}
@Override
public String toString() {
return "Employee [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + "]";
}
}
創(chuàng)建一個測試類StreamAPI.java,,并創(chuàng)建一個test方法嘀倒。所有的創(chuàng)建Stream的方式都在這個類的test方法中。
@Test
public void test() {
}
4.1测蘑、可以通過Collection系列集合提供的stream()或parallelStream()
創(chuàng)建代碼:
// 1.1可以通過Collection系列集合提供的stream()或parallelStream()
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
4.2灌危、通過Arrays中的靜態(tài)方法stream()獲取數(shù)組流
創(chuàng)建代碼:
// 1.2通過Arrays中的靜態(tài)方法stream()獲取數(shù)組流
Employee[] emps = new Employee[10];
Stream<Employee> stream2 = Arrays.stream(emps);
4.3、通過Stream類中的靜態(tài)方法of()
創(chuàng)建代碼:
// 1.3通過Stream類中的靜態(tài)方法of()
Stream<String> stream3 = Stream.of("aa", "bb", "cc");
stream3.forEach(System.out::println);
4.4碳胳、創(chuàng)建無限流
4.4.1勇蝙、迭代
創(chuàng)建代碼:
// 1.4.1、迭代
Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);
stream4.limit(10)
.forEach(System.out::println);
4.4.2挨约、生成
創(chuàng)建代碼:
// 1.4.2味混、生成
Stream.generate(() -> Math.random()).limit(5)
.forEach(System.out::println);
注意:
常用的是第一種跟第二種,這里面獲取的都是串行流(利用Stream)诫惭,還有一種就是并行流翁锡,其獲取方式是parallelStream。
五夕土、中間操作
在中間操作前馆衔,我們先在StreamAPI.java中新創(chuàng)建一個Employee對象的集合,然后每一個中間操作怨绣,我這里都寫了一個測試類角溃。
創(chuàng)建的Employee集合對象如下:
// 2. 中間操作
List<Employee> emps = Arrays.asList(
new Employee(102, "李四", 59, 6666.66),
new Employee(101, "張三", 18, 9999.99),
new Employee(103, "王五", 28, 3333.33),
new Employee(104, "趙六", 8, 7777.77),
new Employee(104, "趙六", 8, 7777.77),
new Employee(104, "趙六", 8, 7777.77),
new Employee(105, "田七", 38, 5555.55)
);
下面的中間操作會用到這個集合。
5.1篮撑、篩選與切片
5.1.1开镣、filter——接收 Lambda , 從流中排除某些元素咽扇。
測試代碼:
// (1)邪财、filter——接收 Lambda , 從流中排除某些元素质欲。
@Test
public void testFilter() {
//這里加入了終止操作 树埠,不然中間操作一系列不會執(zhí)行
//中間操作只有在碰到終止操作才會執(zhí)行
emps.stream()
.filter((e)->e.getAge()>18)
.forEach(System.out::println);//終止操作
}
注意:這里filter主要是過濾一些條件,這里的話就是把年齡小于18歲的Employee對象給過濾掉嘶伟,然后用forEach給遍歷一下怎憋,因為中間操作只有碰到終止操作才會執(zhí)行,不然的話九昧,看不到過濾效果绊袋。以下的操作都大部分都forEach了一下,為方便看到效果铸鹰。filter用的還是很多的癌别。
5.1.2、limit——截斷流蹋笼,使其元素不超過給定數(shù)量展姐。
測試代碼:
// (2)、limit——截斷流剖毯,使其元素不超過給定數(shù)量圾笨。
@Test
public void testLimit() {
emps.stream()
.filter((e)->e.getAge()>8)
.limit(4)//跟數(shù)據(jù)庫中的limit有異曲同工之妙
.forEach(System.out::println);//終止操作
}
注意:這里我利用了上面的filter跟limit,代碼意思是:過濾掉年齡小于8的逊谋,只要4條數(shù)據(jù)擂达。這種"."式操作很有意思,就是中間操作都可以一直".",直到得到你想要的要求胶滋。
5.1.3板鬓、 skip(n) ——跳過元素,返回一個扔掉了前 n 個元素的流镀钓。若流中元素不足 n 個穗熬,則返回一個空流。與 limit(n) 互補
測試代碼:
// (3)丁溅、skip(n) —— 跳過元素唤蔗,返回一個扔掉了前 n 個元素的流。若流中元素不足 n 個窟赏,則返回一個空流垂蜗。與 limit(n) 互補
@Test
public void testSkip() {
emps.stream()
.filter((e)->e.getAge()>8)
.skip(2)//這里可以查找filter過濾后的數(shù)據(jù)俩块,前兩個不要,要后面的,與limit相反
.forEach(System.out::println);//終止操作
}
注意:這里同樣使用了filter中間操作票唆,也可以不用,代碼意思是:過濾掉年齡小于8歲的employee對象肌稻,然后前兩個對象不要,只要后面的對象掘殴。跟limit意思相反。
5.1.4粟誓、distinct——篩選奏寨,通過流所生成元素的 hashCode() 和 equals() 去除重復(fù)元素
測試代碼:
// (4)、distinct——篩選鹰服,通過流所生成元素的 hashCode() 和 equals() 去除重復(fù)元素
@Test
public void testDistinct() {
emps.stream()
.distinct()//去除重復(fù)的元素病瞳,因為通過流所生成元素的 hashCode() 和 equals() 去除重復(fù)元素,所以對象要重寫hashCode跟equals方法
.forEach(System.out::println);//終止操作
}
注意:distinct悲酷,去除重復(fù)的元素套菜,因為通過流所生成元素的 hashCode() 和 equals() 去除重復(fù)元素,所以對象要重寫hashCode跟equals方法设易,我在Employee對象中重寫了這兩個方法逗柴。
5.2、映射
5.2.1亡嫌、map-接收Lambda嚎于,將元素轉(zhuǎn)換成其他形式或提取信息。接收一個函數(shù)作為參數(shù)挟冠,該函數(shù)會被應(yīng)用到每個元素上于购,并將其映射成一個新的元素。
5.2.2知染、flatMap-接收一個函數(shù)作為參數(shù)肋僧,將流中的每個值都轉(zhuǎn)換成另一個流,然后把所有流連接成一個流
測試代碼:
// map-接收Lambda控淡,將元素轉(zhuǎn)換成其他形式或提取信息嫌吠。接收一個函數(shù)作為參數(shù),該函數(shù)會被應(yīng)用到每個元素上掺炭,并將其映射成一個新的元素辫诅。
@Test
public void testMapAndflatMap() {
List<String> list=Arrays.asList("aaa","bbb","ccc","ddd");
list.stream()
.map((str)->str.toUpperCase())//里面是Function
.forEach(System.out::println);
System.out.println("----------------------------------");
//這里是只打印名字,map映射涧狮,根據(jù)Employee::getName返回一個name炕矮,映射成新的及結(jié)果name
emps.stream()
.map(Employee::getName)
.forEach(System.out::println);
System.out.println("======================================");
//流中流
Stream<Stream<Character>> stream = list.stream()
.map(StreamAPI::filterCharacter);
//{{a,a,a},{b,b,b}}
//map是一個個流(這個流中有元素)加入流中
stream.forEach(sm->{
sm.forEach(System.out::println);
});
System.out.println("=============引進flatMap=============");
// 只有一個流
Stream<Character> flatMap = list.stream()
.flatMap(StreamAPI::filterCharacter);
//flatMap是將一個個流中的元素加入流中
//{a,a,a,b,b,b}
flatMap.forEach(System.out::println);
}
/**
* 測試map跟flatMap的區(qū)別
* 有點跟集合中的add跟addAll方法類似
* add是將無論是元素還是集合,整體加到其中一個集合中去[1,2,3.[2,3]]
* addAll是將無論是元素還是集合者冤,都是將元素加到另一個集合中去肤视。[1,2,3,2,3]
* @param str
* @return
*/
public static Stream<Character> filterCharacter(String str){
List<Character> list=new ArrayList<>();
for (Character character : str.toCharArray()) {
list.add(character);
}
return list.stream();
}
注意:map跟flatMap還是有區(qū)別的,map是一個個流(這個流中有元素)加入流中涉枫,flatMap是將一個個流中的元素加入流中邢滑。
5.3、排序
5.3.1愿汰、sorted()---自然排序(Comparable)
5.3.2困后、sorted(Comparator com)----定制排序(Comparator)
測試代碼:
@Test
public void testSorted() {
List<String> list=Arrays.asList("ccc","aaa","bbb","ddd","eee");
list.stream()
.sorted()
.forEach(System.out::println);
System.out.println("=======定制排序=========");
emps.stream()
.sorted((x, y) -> {
if(x.getAge() == y.getAge()){
return x.getName().compareTo(y.getName());
}else{
return Integer.compare(x.getAge(), y.getAge());
}
}).forEach(System.out::println);
}
六乐纸、終止操作
終端操作會從流的流水線生成結(jié)果。其結(jié)果可以是任何不是流的值操灿,例如:List锯仪,Integer,甚至是void趾盐。
在學習終止操作前,我又新建了一個Employee類小腊,如下:Employee2.java
package com.nieshenkuan.pojo;
/**
* 用來測試終止操作
* @author NSK
*
*/
public class Employee2 {
private int id;
private String name;
private int age;
private double salary;
private Status status;
public Employee2() {
}
public Employee2(String name) {
this.name = name;
}
public Employee2(String name, int age) {
this.name = name;
this.age = age;
}
public Employee2(int id, String name, int age, double salary) {
this.id = id;
this.name = name;
this.age = age;
this.salary = salary;
}
public Employee2(int id, String name, int age, double salary, Status status) {
this.id = id;
this.name = name;
this.age = age;
this.salary = salary;
this.status = status;
}
public Status getStatus() {
return status;
}
public void setStatus(Status status) {
this.status = status;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public String show() {
return "測試方法引用救鲤!";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + id;
result = prime * result + ((name == null) ? 0 : name.hashCode());
long temp;
temp = Double.doubleToLongBits(salary);
result = prime * result + (int) (temp ^ (temp >>> 32));
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Employee2 other = (Employee2) obj;
if (age != other.age)
return false;
if (id != other.id)
return false;
if (name == null) {
if (other.name != null)
return false;
} else if (!name.equals(other.name))
return false;
if (Double.doubleToLongBits(salary) != Double.doubleToLongBits(other.salary))
return false;
return true;
}
@Override
public String toString() {
return "Employee2 [id=" + id + ", name=" + name + ", age=" + age + ", salary=" + salary + ", status=" + status
+ "]";
}
public enum Status {
FREE, BUSY, VOCATION;
}
}
然后創(chuàng)建了一個測試終止操作的類,TestShutdown.java
public class TestShutdown {
List<Employee2> emps = Arrays.asList(
new Employee2(102, "李四", 59, 6666.66, Status.BUSY),
new Employee2(101, "張三", 18, 9999.99, Status.FREE),
new Employee2(103, "王五", 28, 3333.33, Status.VOCATION),
new Employee2(104, "趙六", 8, 7777.77, Status.BUSY),
new Employee2(104, "趙六", 8, 7777.77, Status.FREE),
new Employee2(104, "趙六", 8, 7777.77, Status.FREE),
new Employee2(105, "田七", 38, 5555.55, Status.BUSY)
);
}
里面定義了我下面要使用的employee的集合秩冈。
6.1本缠、查找與匹配
6.1.1、allMatch——檢查是否匹配所有元素
測試代碼片段入问,下面有總的代碼:
System.out.println("==========allMatch==============");
boolean allMatch = emps.stream()
.allMatch((e)->e.getStatus().equals(Status.BUSY));
System.out.println(allMatch);
6.1.2丹锹、anyMatch——檢查是否至少匹配一個元素
測試代碼片段:
System.out.println("==========anyMatch==============");
boolean anyMatch = emps.stream()
.anyMatch((e)->e.getAge()>10);
System.out.println(anyMatch);
6.1.3、noneMatch——檢查是否沒有匹配的元素
測試代碼片段:
System.out.println("==========noneMatch==============");
boolean noneMatch = emps.stream()
.noneMatch((e)->e.getStatus().equals(Status.BUSY));
System.out.println(noneMatch);
6.1.4芬失、findFirst——返回第一個元素
測試代碼片段:
System.out.println("==========findFirst==============");
Optional<Employee2> findFirst = emps.stream()
.sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))//按照工資排序并輸出第一個
.findFirst();
System.out.println(findFirst);
6.1.5楣黍、findAny——返回當前流中的任意元素
測試代碼片段:
System.out.println("==========findAny==============");
Optional<Employee2> findAny = emps.stream()
.filter((e)->e.getStatus().equals(Status.BUSY))
.findAny();
System.out.println(findAny);
6.1.6、count——返回流中元素的總個數(shù)
測試代碼片段:
System.out.println("==========count==============");
long count = emps.stream()
.count();
System.out.println(count);
6.1.7棱烂、max——返回流中最大值
測試代碼片段:
System.out.println("==========max==============");
Optional<Double> max = emps.stream()
.map(Employee2::getSalary)
.max(Double::compare);
System.out.println(max);
6.1.8租漂、min——返回流中最小值
測試代碼片段:
System.out.println("==========min==============");
Optional<Employee2> min = emps.stream()
.min((e1,e2)->Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println(min);
總的測試代碼:
//3. 終止操作
/*查找與匹配
allMatch——檢查是否匹配所有元素
anyMatch——檢查是否至少匹配一個元素
noneMatch——檢查是否沒有匹配的元素
findFirst——返回第一個元素
findAny——返回當前流中的任意元素
count——返回流中元素的總個數(shù)
max——返回流中最大值
min——返回流中最小值
*/
@Test
public void test() {
// emps.stream():獲取串行流
// emps.parallelStream():獲取并行流
System.out.println("==========allMatch==============");
boolean allMatch = emps.stream()
.allMatch((e)->e.getStatus().equals(Status.BUSY));
System.out.println(allMatch);
System.out.println("==========anyMatch==============");
boolean anyMatch = emps.stream()
.anyMatch((e)->e.getAge()>10);
System.out.println(anyMatch);
System.out.println("==========noneMatch==============");
boolean noneMatch = emps.stream()
.noneMatch((e)->e.getStatus().equals(Status.BUSY));
System.out.println(noneMatch);
System.out.println("==========findFirst==============");
Optional<Employee2> findFirst = emps.stream()
.sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))//按照工資排序并輸出第一個
.findFirst();
System.out.println(findFirst);
System.out.println("==========findAny==============");
Optional<Employee2> findAny = emps.stream()
.filter((e)->e.getStatus().equals(Status.BUSY))
.findAny();
System.out.println(findAny);
System.out.println("==========count==============");
long count = emps.stream()
.count();
System.out.println(count);
System.out.println("==========max==============");
Optional<Double> max = emps.stream()
.map(Employee2::getSalary)
.max(Double::compare);
System.out.println(max);
System.out.println("==========min==============");
Optional<Employee2> min = emps.stream()
.min((e1,e2)->Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println(min);
}
6.2、歸約
6.2.1颊糜、reduce(T identity, BinaryOperator) / reduce(BinaryOperator) ——可以將流中元素反復(fù)結(jié)合起來哩治,得到一個值。
測試代碼:
@Test
public void testReduce() {
List<Integer> list= Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer sum = list.stream()
.reduce(0,(x,y)->x+y);
System.out.println(sum);
Optional<Double> reduce = emps.stream()
.map(Employee2::getSalary)
.reduce(Double::sum);
System.out.println(reduce.get());
}
6.3衬鱼、收集
Collector接口中方法的實現(xiàn)決定了如何對流執(zhí)行收集操作(如收集到List业筏、Set、Map)鸟赫。但是Collectors實用類提供了很多靜態(tài)方法蒜胖,可以方便地創(chuàng)建常見收集器實例,具體方法與實例如下表:
6.3.1惯疙、Collectors.toList()
測試代碼片段:
List<String> collect = emps.stream()
.map(Employee2::getName)
.collect(Collectors.toList());
collect.forEach(System.out::println);
6.3.2翠勉、Collectors.toSet()
測試代碼片段:
Set<String> collect2 = emps.stream()
.map(Employee2::getName)
.collect(Collectors.toSet());
collect2.forEach(System.out::println);
6.3.3、Collectors.toCollection(HashSet::new)
測試代碼片段:
HashSet<String> collect3 = emps.stream()
.map(Employee2::getName)
.collect(Collectors.toCollection(HashSet::new));
collect3.forEach(System.out::println);
6.3.4霉颠、Collectors.maxBy()
測試代碼片段:
Optional<Double> collect = emps.stream()
.map(Employee2::getSalary)
.collect(Collectors.maxBy(Double::compare));
System.out.println(collect.get());
Optional<Employee2> collect2 = emps.stream()
.collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
System.out.println(collect2.get());
6.3.5对碌、Collectors.minBy()
測試代碼片段:
Optional<Double> collect4 = emps.stream()
.map(Employee2::getSalary)
.collect(Collectors.minBy(Double::compare));
System.out.println(collect4);
Optional<Employee2> collect3 = emps.stream()
.collect(Collectors.minBy((e1,e2)->Double.compare(e1.getSalary(),e2.getSalary())));
System.out.println(collect3.get());
6.3.6、Collectors.summingDouble()
測試代碼片段:
Double collect5 = emps.stream()
.collect(Collectors.summingDouble(Employee2::getSalary));
System.out.println(collect5);
6.3.7蒿偎、Collectors.averagingDouble()
測試代碼片段:
Double collect6 = emps.stream()
.collect(Collectors.averagingDouble((e)->e.getSalary()));
Double collect7 = emps.stream()
.collect(Collectors.averagingDouble(Employee2::getSalary));
System.out.println("collect6:"+collect6);
System.out.println("collect7:"+collect7);
6.3.8朽们、Collectors.counting()
測試代碼片段:
//總數(shù)
Long collect8 = emps.stream()
.collect(Collectors.counting());
System.out.println(collect8);
6.3.9怀读、Collectors.summarizingDouble()
測試代碼片段:
DoubleSummaryStatistics collect9 = emps.stream()
.collect(Collectors.summarizingDouble(Employee2::getSalary));
long count = collect9.getCount();
double average = collect9.getAverage();
double max = collect9.getMax();
double min = collect9.getMin();
double sum = collect9.getSum();
System.out.println("count:"+count);
System.out.println("average:"+average);
System.out.println("max:"+max);
System.out.println("min:"+min);
System.out.println("sum:"+sum);
6.3.10、分組Collectors.groupingBy()
測試代碼片段:
//分組
@Test
public void testCollect3() {
Map<Status, List<Employee2>> collect = emps.stream()
.collect(Collectors.groupingBy((e)->e.getStatus()));
System.out.println(collect);
Map<Status, List<Employee2>> collect2 = emps.stream()
.collect(Collectors.groupingBy(Employee2::getStatus));
System.out.println(collect2);
}
6.3.11骑脱、多級分組Collectors.groupingBy()
測試代碼片段:
//多級分組
@Test
public void testCollect4() {
Map<Status, Map<String, List<Employee2>>> collect = emps.stream()
.collect(Collectors.groupingBy(Employee2::getStatus, Collectors.groupingBy((e)->{
if(e.getAge() >= 60)
return "老年";
else if(e.getAge() >= 35)
return "中年";
else
return "成年";
})));
System.out.println(collect);
}
6.3.12菜枷、分區(qū)Collectors.partitioningBy()
測試代碼片段:
//多級分組
@Test
public void testCollect4() {
Map<Status, Map<String, List<Employee2>>> collect = emps.stream()
.collect(Collectors.groupingBy(Employee2::getStatus, Collectors.groupingBy((e)->{
if(e.getAge() >= 60)
return "老年";
else if(e.getAge() >= 35)
return "中年";
else
return "成年";
})));
System.out.println(collect);
}
6.3.13、組接字符串Collectors.joining()
測試代碼片段:
//組接字符串
@Test
public void testCollect6() {
String collect = emps.stream()
.map((e)->e.getName())
.collect(Collectors.joining());
System.out.println(collect);
String collect3 = emps.stream()
.map(Employee2::getName)
.collect(Collectors.joining(","));
System.out.println(collect3);
String collect2 = emps.stream()
.map(Employee2::getName)
.collect(Collectors.joining(",", "prefix", "subfix"));
System.out.println(collect2);
}
@Test
public void testCollect7() {
Optional<Double> collect = emps.stream()
.map(Employee2::getSalary)
.collect(Collectors.reducing(Double::sum));
System.out.println(collect.get());
}
測試代碼片段:
/**
* collect——將流轉(zhuǎn)換為其他形式叁丧。接收一個 Collector接口的實現(xiàn)啤誊,用于給Stream中元素做匯總的方法
*/
@Test
public void testCollect() {
List<String> collect = emps.stream()
.map(Employee2::getName)
.collect(Collectors.toList());
collect.forEach(System.out::println);
Set<String> collect2 = emps.stream()
.map(Employee2::getName)
.collect(Collectors.toSet());
collect2.forEach(System.out::println);
HashSet<String> collect3 = emps.stream()
.map(Employee2::getName)
.collect(Collectors.toCollection(HashSet::new));
collect3.forEach(System.out::println);
}
@Test
public void testCollect2() {
Optional<Double> collect = emps.stream()
.map(Employee2::getSalary)
.collect(Collectors.maxBy(Double::compare));
System.out.println(collect.get());
Optional<Employee2> collect2 = emps.stream()
.collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
System.out.println(collect2.get());
Optional<Double> collect4 = emps.stream()
.map(Employee2::getSalary)
.collect(Collectors.minBy(Double::compare));
System.out.println(collect4);
Optional<Employee2> collect3 = emps.stream()
.collect(Collectors.minBy((e1,e2)->Double.compare(e1.getSalary(),e2.getSalary())));
System.out.println(collect3.get());
System.out.println("=========================================");
Double collect5 = emps.stream()
.collect(Collectors.summingDouble(Employee2::getSalary));
System.out.println(collect5);
Double collect6 = emps.stream()
.collect(Collectors.averagingDouble((e)->e.getSalary()));
Double collect7 = emps.stream()
.collect(Collectors.averagingDouble(Employee2::getSalary));
System.out.println("collect6:"+collect6);
System.out.println("collect7:"+collect7);
//總數(shù)
Long collect8 = emps.stream()
.collect(Collectors.counting());
System.out.println(collect8);
DoubleSummaryStatistics collect9 = emps.stream()
.collect(Collectors.summarizingDouble(Employee2::getSalary));
long count = collect9.getCount();
double average = collect9.getAverage();
double max = collect9.getMax();
double min = collect9.getMin();
double sum = collect9.getSum();
System.out.println("count:"+count);
System.out.println("average:"+average);
System.out.println("max:"+max);
System.out.println("min:"+min);
System.out.println("sum:"+sum);
}
//分組
@Test
public void testCollect3() {
Map<Status, List<Employee2>> collect = emps.stream()
.collect(Collectors.groupingBy((e)->e.getStatus()));
System.out.println(collect);
Map<Status, List<Employee2>> collect2 = emps.stream()
.collect(Collectors.groupingBy(Employee2::getStatus));
System.out.println(collect2);
}
//多級分組
@Test
public void testCollect4() {
Map<Status, Map<String, List<Employee2>>> collect = emps.stream()
.collect(Collectors.groupingBy(Employee2::getStatus, Collectors.groupingBy((e)->{
if(e.getAge() >= 60)
return "老年";
else if(e.getAge() >= 35)
return "中年";
else
return "成年";
})));
System.out.println(collect);
}
//分區(qū)
@Test
public void testCollect5() {
Map<Boolean, List<Employee2>> collect = emps.stream()
.collect(Collectors.partitioningBy((e)->e.getSalary()>5000));
System.out.println(collect);
}
//組接字符串
@Test
public void testCollect6() {
String collect = emps.stream()
.map((e)->e.getName())
.collect(Collectors.joining());
System.out.println(collect);
String collect3 = emps.stream()
.map(Employee2::getName)
.collect(Collectors.joining(","));
System.out.println(collect3);
String collect2 = emps.stream()
.map(Employee2::getName)
.collect(Collectors.joining(",", "prefix", "subfix"));
System.out.println(collect2);
}
@Test
public void testCollect7() {
Optional<Double> collect = emps.stream()
.map(Employee2::getSalary)
.collect(Collectors.reducing(Double::sum));
System.out.println(collect.get());
}