1、stream API——相識
Stream是元素的集合,這點讓Stream看起來有些類似Iterator;可以支援順序和并行的對原Stream進行彙聚的操作。
大家可以把Stream當成一個進階版本的Iterator。原始版本的Iterator,使用者隻能一個一個的周遊元素并對其執行某些操作;高版本的Stream,使用者隻要給出需要對其包含的元素執行什麼操作,比如:“過濾掉長度大于10的字元串”、“擷取每個字元串的首字母”等,這些操作如何應用到每個元素上,就給Stream就好了!
2、Stream API——建立、中間操作、終止操作(終端操作)
建立:一個資料源(如:集合、數組),擷取一個流。
// 建立Stream
@Test
public void fun1(){
// 1.可以通過Collection系列集合提供的stream()串行流或parallelStream()并行流
List<String> list = new ArrayList<>();
Stream<String> stream1 = list.stream();
// 2.通過Arrays中的靜态方法stream()獲得數組流
Employee [] emps = new Employee[10];
Stream<Employee> stream2 = Arrays.stream(emps);
// 3.通過Stream類中的靜态方法of()
Stream<String> stream3 = Stream.of("aa","bb","cc");
// 4.建立無限流
// (1)疊代
Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);
stream4.limit(10)
.forEach(System.out::println);
// (2)生成
Stream.generate(() -> Math.random())
.limit(5)
.forEach(System.out::println);
}
中間操作:一個中間操作鍊,對資料源的資料進行處理。
(1)、篩選與切片
// 中間操作
/*
篩選和切片
filter——接收Lambda,從流中排除某些元素。
limit——截斷流,使其元素不超過給定數量。
skip(n)——跳過元素,傳回一個扔掉了前n個元素的流,若流中元素不足n個時,則傳回一個空流,與limit互補
distinct——篩選,通過流所生成元素的HashCode()和equals()去除重複元素
*/
List<Employee> employees = Arrays.asList(
new Employee("張三",18,9999.99),
new Employee("張三",18,9999.99),
new Employee("張三",18,9999.99),
new Employee("張三",18,9999.99),
new Employee("張三",18,9999.99),
new Employee("張三",18,9999.99),
new Employee("李四",18,8888.88),
new Employee("王五",100,1.11),
new Employee("趙六",80,2.22),
new Employee("田七",20,9898.98)
);
/*内部疊代:疊代操作由Stream API完成*/
@Test
public void fun2(){
// 中間操作:不會執行任何操作
Stream<Employee> stream = employees.stream()
.filter((e) -> {
System.out.println("Stream API的中間操作");
System.out.println("沒有終止操作的話,中間操作不執行。");
return e.getAge() > 35;
});
// 終止操作:一次性執行全部内容,即惰性求值
stream.forEach(System.out::println);
}
/*外部疊代*/
@Test
public void fun3(){
Iterator<Employee> iterator = employees.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
@Test
public void fun4(){
employees.stream()
.filter((e) -> {
System.out.println("短路!"); //&& ||
return e.getSalary() >5000;
})
.limit(2)
.forEach(System.out::println);
}
@Test
public void fun5(){
employees.stream()
.filter((e) -> e.getSalary()>5000)
.skip(2)
.forEach(System.out::println);
}
@Test
public void fun6(){
employees.stream()
.filter((e) -> e.getSalary()>5000)
.distinct()
.forEach(System.out::println);
}
package Lambda.LambdaCase;
public class Employee {
private String name;
private Integer age;
private Double salary;
public Employee() {
}
public Employee(Integer age) {
this.name = name;
}
public Employee(String name, Integer age) {
this.name = name;
this.age = age;
}
public Employee(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 boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Employee employee = (Employee) o;
if (!name.equals(employee.name)) return false;
if (!age.equals(employee.age)) return false;
return salary.equals(employee.salary);
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + age.hashCode();
result = 31 * result + salary.hashCode();
return result;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", age=" + age +
", salary=" + salary +
'}';
}
}
(2).映射
/*
映射
map——接收lambda,将元素轉換成其他形式或提取資訊。
接收一個函數作為參數,該函數會應用到每個元素上,并将其映射成一個新的元素。
flagMap——接收一個函數作為參數,将流中的每個值都換成另一個流,然後把所有流連接配接成一個流。
*/
@Test
public void fun7(){
List<String> list = Arrays.asList("aaa","bbb","ccc","ddd","eee");
list.stream()
.map((str) -> str.toUpperCase())
.forEach(System.out::println);
System.out.println("------------我是分割線-------------");
employees.stream()
.map(Employee::getName)
.forEach(System.out::println);
System.out.println("------------我是分割線-------------");
Stream<Stream<Character>> stream = list.stream()
.map(GetUnlimitedFlow::filterCharacter);//{{a,a,a},{b,b,b}}
stream.forEach((sm) ->{
sm.forEach(System.out::println);
});
System.out.println("------------我是分割線-------------");
Stream<Character> stream1 = list.stream()
.flatMap(GetUnlimitedFlow::filterCharacter);//{a,a,a,b,b,b}
stream1.forEach(System.out::println);
}
/*解析字元串,将字元串中的字元一個個列印出來*/
public static Stream<Character> filterCharacter(String str){//add(Object obj) addAll(Collection coll)
ArrayList<Character> list = new ArrayList<>();
for (Character ch:str.toCharArray()) {
list.add(ch);
}
return list.stream();
}
@Test
public void fun8(){
List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
ArrayList list1 = new ArrayList();
list1.add(11);
list1.add(33);
// list1.add(list);
// System.out.println(list1);
list1.addAll(list);
System.out.println(list1);
}
(3).排序
/*
排序
sorted()——自然排序(Comparable)
sorted(Comparator com)——定制排序(Comparater)
*/
@Test
public void fun9(){
List<String> list = Arrays.asList("bbb", "ddd", "aaa", "eee", "ccc");
list.stream()
.sorted()
.forEach(System.out::println);
System.out.println("------------我是分割線-------------");
employees.stream()
.sorted((e1,e2) -> {
if (e1.getAge().equals(e2.getAge())){
return e1.getName().compareTo(e2.getName());
}else {
return -e1.getAge().compareTo(e2.getAge());
}
}).forEach(System.out::println);
}
終止操作:一個終止操作,執行中間操作鍊,并産生結果。
查找與比對
List<Employee> employees1 = Arrays.asList(
new Employee("張三",18,9999.99, Employee.Status.BUSY),
new Employee("李四",18,8888.88, Employee.Status.FREE),
new Employee("王五",100,1.11, Employee.Status.VOCATION),
new Employee("趙六",80,2.22, Employee.Status.FREE),
new Employee("田七",20,9898.98, Employee.Status.BUSY)
);
/*
查找與比對
allMatch——檢查是否比對所有元素
anyMatch——檢查是否至少比對一個元素
noneMatch——檢查是否沒有比對所有元素
findFirst——傳回第一個元素
findAny——傳回目前流中的任意元素
count——傳回流中元素的總個數
max——傳回流中最大值
min——傳回流中最小值
*/
@Test
public void fun10(){
boolean b1 = employees1.stream()
.allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b1);
boolean b2 = employees1.stream()
.anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b2);
boolean b3 = employees1.stream()
.noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
System.out.println(b3);
Optional<Employee> op = employees1.stream()
.sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
.findFirst();
System.out.println(op.get());
Optional<Employee> any = employees1.stream()
.filter((e) -> e.getStatus().equals(Employee.Status.BUSY))
.findAny();
System.out.println(any.get());
}
@Test
public void fun11() {
long count = employees1.stream()
.count();
System.out.println(count);
Optional<Employee> max = employees1.stream()
.max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println(max.get());
Optional<Double> min = employees1.stream()
.map(Employee::getSalary)
.min(Double::compare);
System.out.println(min.get());
}
歸約
/*
歸約
reduce(T identity,BinaryOperator)/reduce(BinaryOperator)
——可以将流中元素反複結合起來,得到一個值
*/
@Test
public void fun12(){
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);
System.out.println("------------我是分割線-------------");
Optional<Double> reduce = employees1.stream()
.map(Employee::getSalary)
.reduce(Double::sum);
System.out.println(reduce.get());
}
收集
/*
收集:
collect——将流轉換為其他形式,接收一個Collector接口的實作,
用于給Stream中元素做彙總的方法。
*/
@Test
public void fun13(){
List<String> list = employees1.stream()
.map(Employee::getName)
.collect(Collectors.toList());
list.forEach(System.out::println);
System.out.println("------------我是分割線-------------");
Set<String> set = employees1.stream()
.map(Employee::getName)
.collect(Collectors.toSet());
set.forEach(System.out::println);
System.out.println("------------我是分割線-------------");
HashSet<Double> hashSet = employees1.stream()
.map(Employee::getSalary)
.collect(Collectors.toCollection(HashSet::new));
hashSet.forEach(System.out::println);
}
@Test
public void fun14(){
// 總數
Long count = employees1.stream()
.collect(Collectors.counting());
System.out.println(count);
System.out.println("------------我是分割線-------------");
// 平均值
Double avg = employees1.stream()
.collect(Collectors.averagingDouble(Employee::getSalary));
System.out.println(avg);
System.out.println("------------我是分割線-------------");
// 總和
Double sum = employees1.stream()
.collect(Collectors.summingDouble(Employee::getSalary));
System.out.println(sum);
System.out.println("------------我是分割線-------------");
// 最大值
Optional<Employee> max = employees1.stream()
.collect(Collectors.maxBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
System.out.println(max.get());
System.out.println("------------我是分割線-------------");
// 最小值
Optional<Double> min = employees1.stream()
.map(Employee::getSalary)
.collect(Collectors.minBy(Double::compare));
System.out.println(min.get());
}
分組和多級分組
@Test
public void fun15(){
// 分組
Map<Employee.Status, List<Employee>> map = employees1.stream()
.collect(Collectors.groupingBy(Employee::getStatus));
System.out.println(map);
}
// 多級分組
@Test
public void fun16(){
Map<Employee.Status, Map<String, List<Employee>>> mapMap = employees1.stream()
.collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
if (e.getAge() < 5) {
return "青年";
} else if (e.getAge() < 10) {
return "中年";
} else {
return "老年";
}
})));
System.out.println(mapMap);
}
分區
// 分區
@Test
public void fun17(){
Map<Boolean, List<Employee>> partition = employees1.stream()
.collect(Collectors.partitioningBy((e) -> e.getSalary() > 8000));
System.out.println(partition);
}
彙總統計
// 彙總統計
@Test
public void fun18(){
DoubleSummaryStatistics summary = employees1.stream()
.collect(Collectors.summarizingDouble(Employee::getSalary));
System.out.println(summary);
System.out.println(summary.getAverage());
System.out.println(summary.getCount());
System.out.println(summary.getMax());
System.out.println(summary.getMin());
System.out.println(summary.getSum());
}
字元串拼接
// 字元串拼接
@Test
public void fun19(){
String join = employees1.stream()
.map(Employee::getName)
.collect(Collectors.joining(",","===","==="));
System.out.println(join);
}
package Steam;
import Lambda.LambdaCase.Employee;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
public class TestStreamAPI {
/*
1、給定一個數字清單,如何傳回一個由每個數的平方構成的清單呢?
給定【1,2,3,4,5】,應該傳回【1,4,9,16,25】
*/
@Test
public void fun1(){
Integer [] arr = new Integer[]{1,2,3,4,5};
Arrays.stream(arr)
.map((x) -> x*x)
.forEach(System.out::println);
}
/*
2、怎樣用map和reduce方法數一數流中有多少個Employee?
*/
List<Employee> employees = Arrays.asList(
new Employee("張三",18,9999.99, Employee.Status.BUSY),
new Employee("李四",18,8888.88, Employee.Status.FREE),
new Employee("王五",100,1.11, Employee.Status.VOCATION),
new Employee("趙六",80,2.22, Employee.Status.FREE),
new Employee("田七",20,9898.98, Employee.Status.BUSY)
);
@Test
public void fun2(){
Optional<Integer> sum = employees.stream()
.map((e) -> 1)
.reduce(Integer::sum);
System.out.println(sum.get());
}
}