Java 8新特性簡介
Java 8 (又稱為 jdk 1.8) 是 Java 語言開發的一個主要版本,Java 8 是oracle公司于2014年3月發布,可以看成是自Java 5 以來最具革命性的版本,Java 8為Java語言、編譯器、類別庫、開發工具與JVM帶來了大量新特性,



Lambda運算式



import org.junit.Test;
import java.util.Comparator;
/**
Lambda 運算式的使用舉例
*/
public class Lambda {
@Test
public void test1(){
Runnable r1 = new Runnable() {//提供一個實作 runnable 介面的匿名實作類物件
@Override
public void run() {
System.out.println("helloWorld");
}
};
r1.run();//helloWorld
System.out.println("***********************");
Runnable r2 = () -> System.out.println("hi");
r2.run();
}
@Test
public void test2(){
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return Integer.compare(o1,o2);
}
};
int compare1 = com1.compare(12, 13);
System.out.println(compare1);//-1
System.out.println("*******************************");
//Lambda 運算式的寫法
Comparator<Integer> com2 = (o1,o2)->Integer.compare(o1,o2);
int compare2 = com2.compare(56, 13);
System.out.println(compare2);//-1
System.out.println("*************************");
//方法參考
Comparator<Integer> com3 = Integer::compareTo;
int compare3 = com3.compare(56, 456);
System.out.println(compare3);//-1
}
}




Lambda 運算式的使用
1、舉例: (o1,o2) -> Integer.compare(o1,o2);
2、格式:
-> : lambda 運算子或箭頭運算子
->左邊 : lambda形參串列(其實就是介面中的抽象方法形參串列)
->右邊 : lambda體(其實就是重寫的抽象方法的方法體)
3、Lambda 運算式的使用:(分為6種情況介紹)
總結:
左邊:Lambda 形參串列的引數型別可以省略(型別推斷);如果引數串列的引數只有一個引數,其一對小括號可以省略
右邊:Lambda 體應該使用一堆{}包裹;如果Lambda體只有一條執行陳述句(可能時return陳述句),可以省略大括號以及return關鍵字
4、Lambda運算式的本質:作為函式式介面的實體
5、如果一個介面中,只宣告了一個抽象方法,則這個介面稱之為函式式介面,我們可以在一個介面上使用 @FunctionalInterface 注解,這樣做可以檢查它是否是一個函式式介面,
6、以前用匿名實作類表示的現在都可以用Lambda運算式來寫,
import org.junit.Test;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.function.Consumer;
public class LambdaTest1 {
//語法格式一:無參,無回傳值
@Test
public void test1(){
Runnable r1 = new Runnable() {//提供一個實作 runnable 介面的匿名實作類物件
@Override
public void run() {
System.out.println("helloWorld");
}
};
r1.run();//helloWorld
System.out.println("***********************");
Runnable r2 = () -> {
System.out.println("hi");
};
r2.run();
}
//語法格式二:Lambda 需要一個引數,但沒有回傳值,
@Test
public void test2(){
Consumer<String> con = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
con.accept("helloWorld");
System.out.println("**************************");
Consumer<String> con2 = (String s)-> {
System.out.println(s);
};
con2.accept("Hi");
}
//語法格式三:資料型別可以省略,因為可以由編譯器推斷得出,稱為“型別推斷”
@Test
public void test3(){
Consumer<String> con2 = (String s)-> {
System.out.println(s);
};
con2.accept("Hi");
System.out.println("******************************");
Consumer<String> con3 = (s)-> {
System.out.println(s);
};
con3.accept("Hi3");
//型別推斷舉例
ArrayList<String> list = new ArrayList<>();//型別推斷
int[] arr = {1,2,3};//型別推斷
}
//型別推斷四:Lambda 若只需要一個引數時,引數的小括號可以省略
@Test
public void test4(){
Consumer<String> con3 = (s)-> {
System.out.println(s);
};
con3.accept("Hi3");
System.out.println("*************************");
Consumer<String> con4 = s-> {
System.out.println(s);
};
con4.accept("Hi4");
}
//語法格式五:Lambda 需要兩個或以上的引數,多條執行陳述句,并且可以有回傳值
@Test
public void test5(){
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
}
};
System.out.println(com1.compare(12, 45));
System.out.println("*********************************");
Comparator<Integer> com2 = (o1,o2)->{
System.out.println(o1);
System.out.println(o2);
return o1.compareTo(o2);
};
System.out.println(com2.compare(12,4));
}
//語法格式六:當 Lambda 體只有一條陳述句時,return 與大括號若有,都可以省略
@Test
public void test6(){
Comparator<Integer> com1 = new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o1.compareTo(o2);
}
};
System.out.println(com1.compare(12, 45));
System.out.println("*****************************");
Comparator<Integer> com2 = (o1,o2) -> o1.compareTo(o2);
System.out.println(com2.compare(12, 5));
}
@Test
public void test7(){
Consumer<String> con4 = s-> {
System.out.println(s);
};
con4.accept("Hi4");
System.out.println("*****************************");
Consumer<String> con5 = s-> System.out.println(s);
con5.accept("Hi5");
}
}
函式式(Functional)介面

Lambda 運算式依賴于函式式介面,Lambda 運算式只能用在只有一個抽象方法的介面上,
Lambda運算式的本質:作為函式式介面的實體






import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
java 內置的四大核心函式式介面
消費型介面: Consumer<T> void accept(T t)
供給型介面: Supplier<T> T get()
函式型介面: Function<T,R> R apply(T t)
斷定型介面: Predicate<T> boolean test(T t)
*/
public class LambdaTest2 {
@Test
public void test1(){
happytime(500, new Consumer<Double>() {
@Override
public void accept(Double aDouble) {
System.out.println("揮霍"+aDouble+"塊");
}
});
System.out.println("*******************************");
happytime(400,money->System.out.println("揮霍"+money+"塊"));
}
public void happytime(double money, Consumer<Double> con){
con.accept(money);
}
@Test
public void test2(){
List<String> list = Arrays.asList("北京","南京","天津","東京","普京");
List<String> filterStrs = filterString(list, new Predicate<String>() {
@Override
public boolean test(String s) {
return s.contains("京");
}
});
System.out.println(filterStrs);
System.out.println("***********************************");
List<String> filterStrs2 = filterString(list,s -> s.contains("京"));
System.out.println(filterStrs2);
}
//根據給定的規則,過濾集合中的字串,此規則由 Predicate 的抽象方法決定
public List<String> filterString(List<String> list, Predicate<String> pre){
ArrayList<String> filter = new ArrayList<>();
for (String s: list) {
if (pre.test(s)){
filter.add(s);
}
}
return filter;
}
}
方法參考與構造器參考
方法參考與構造器參考的概念
在某些特殊情況下,可以不使用 Lambda 運算式,改用方法參考





package java2;
/**
* 創建一個Employee 類,方便后面舉例呼叫
* @author shkstart 郵箱:shkstart@126.com
*/
public class Employee {
private int id;
private String name;
private int age;
private double 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 Employee() {
}
public Employee(int id) {
this.id = id;
}
public Employee(int id, String name) {
this.id = id;
this.name = name;
}
public Employee(int id, String name, int age, double salary) {
this.id = id;
this.name = name;
this.age = age;
this.salary = salary;
}
@Override
public String toString() {
return "Employee{" + "id=" + id + ", 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;
Employee employee = (Employee) o;
if (id != employee.id)
return false;
if (age != employee.age)
return false;
if (Double.compare(employee.salary, salary) != 0)
return false;
return name != null ? name.equals(employee.name) : employee.name == null;
}
@Override
public int hashCode() {
int result;
long temp;
result = id;
result = 31 * result + (name != null ? name.hashCode() : 0);
result = 31 * result + age;
temp = Double.doubleToLongBits(salary);
result = 31 * result + (int) (temp ^ (temp >>> 32));
return result;
}
}
package java2;
import java.util.ArrayList;
import java.util.List;
/**
* 提供用于測驗的資料
*
* @author shkstart 郵箱:shkstart@126.com
*/
public class EmployeeData {
public static List<Employee> getEmployees(){
List<Employee> list = new ArrayList<>();
list.add(new Employee(1001, "馬化騰", 34, 6000.38));
list.add(new Employee(1002, "馬云", 12, 9876.12));
list.add(new Employee(1003, "劉強東", 33, 3000.82));
list.add(new Employee(1004, "雷軍", 26, 7657.37));
list.add(new Employee(1005, "李彥宏", 65, 5555.32));
list.add(new Employee(1006, "比爾蓋茨", 42, 9500.43));
list.add(new Employee(1007, "任正非", 26, 4333.32));
list.add(new Employee(1008, "扎克伯格", 35, 2500.32));
return list;
}
}
方法參考的測驗
package java2;
/**
* 方法參考的使用
* 1、使用情景: 當要傳遞給Lambda體的操作,已經有實作的方法了,可以使用方法參考
* 2、方法參考本質上就是 lambda 運算式,而 lambda 運算式作為函式式介面的實體出現的,
* 所以方法參考,也是函式式介面的實體
* 3、使用格式: 類(或物件) :: 方法名
*
* 4、具體分為如下三種情況:
* 情況一 物件 :: 非靜態方法
* 情況二 類 :: 靜態方法
* 情況三 類 :: 非靜態方法
* 5、方法參考使用的要求:要求 (介面中的抽象方法的形參串列和回傳值型別) 與 (方法參考的方法的形參串列和回傳值串列) 相同!(針對情況一和情況二)
*/
import org.junit.Test;
import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;
public class MethodRefTest {
// 情況一:物件 :: 實體方法
//Consumer中的void accept(T t)
//PrintStream中的void println(T t)
@Test
public void test1() {
Consumer<String> con1 = s -> System.out.println(s);
con1.accept("java");
System.out.println("*********************************");
PrintStream ps = System.out;
Consumer<String> con2 = ps::println;
con2.accept("javaSE");
}
//Supplier中的T get()
//Employee中的String getName()
@Test
public void test2() {
Employee emp = new Employee(1001,"Tom",23,5600);
Supplier<String> sup1 = ()->emp.getName();
System.out.println(sup1.get());
System.out.println("*********************************");
Supplier<String> sup2 = emp::getName;
System.out.println(sup2.get());
}
// 情況二:類 :: 靜態方法
//Comparator中的int compare(T t1,T t2)
//Integer中的int compare(T t1,T t2)
@Test
public void test3() {
Comparator<Integer> com1 = (t1, t2)->Integer.compare(t1,t2);
System.out.println(com1.compare(12,56));
System.out.println("***************************************");
Comparator<Integer> com2 = Integer::compare;
System.out.println(com1.compare(45,5));
}
//Function中的R apply(T t)
//Math中的Long round(Double d)
@Test
public void test4() {
Function<Double,Long> fun1 = new Function<Double, Long>() {
@Override
public Long apply(Double aDouble) {
return Math.round(aDouble);
}
};
System.out.println(fun1.apply(12.0));
System.out.println("***********************************");
Function<Double,Long> fun2 = d -> Math.round(d);//Double 為引數型別 , Long為回傳值型別
System.out.println(fun2.apply(45.0));
System.out.println("*********************************");
Function<Double,Long> fun3 = Math::round;
System.out.println(fun3.apply(78.0));
}
// 情況三:類 :: 實體方法
// Comparator中的int comapre(T t1,T t2)
// String中的int t1.compareTo(t2)
@Test
public void test5() {
Comparator<String> com1 = (s1,s2) -> s1.compareTo(s2);
System.out.println(com1.compare("abc","cds"));
System.out.println("************************************************");
Comparator<String> com2= String :: compareTo;
System.out.println(com2.compare("455","889"));
}
//BiPredicate中的boolean test(T t1, T t2);
//String中的boolean t1.equals(t2)
@Test
public void test6() {
BiPredicate<String,String> bip1 = (s1, s2) -> s1.equals(s2);
System.out.println(bip1.test("abc","abc"));
System.out.println("*************************************************");
BiPredicate<String,String> bip2 = String::equals;
System.out.println(bip2.test("bcd","cas"));
}
// Function中的R apply(T t)
// Employee中的String getName();
@Test
public void test7() {
Employee jerry = new Employee(1001, "Jerry");
Function<Employee,String> fun1 = (employee) -> employee.getName();
System.out.println(fun1.apply(jerry));
System.out.println("************************************************");
Function<Employee,String> fun2 = Employee::getName;
System.out.println(fun2.apply(jerry));
}
}
構造器參考和陣列參考
package java2;
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Supplier;
/**
* 一、構造器參考
* 和方法參考類似,函式式介面的抽像方法的形參和構造器的形參串列串列一致,
* 抽象方法的回傳值型別即為構造器所屬的類的型別,
*
* 二、陣列參考
* 可以把陣列看做是一個特殊的類,則寫法與構造器參考一致,
*
*
* Created by shkstart
*/
public class ConstructorRefTest {
//構造器參考
//一個引數
//Supplier中的T get()
//Employee 的空參構造器:Employee()
@Test
public void test1(){
Supplier<Employee> sup1 = new Supplier<Employee>() {
@Override
public Employee get() {
return new Employee();
}
};
System.out.println(sup1.get());
System.out.println("*******************************************");
Supplier<Employee> sup2 = () -> new Employee();
System.out.println(sup2.get());
System.out.println("******************************************");
Supplier<Employee> sup3 = Employee::new;
System.out.println(sup3.get());
}
//Function中的R apply(T t)
@Test
public void test2(){
Function<Integer,Employee> fun = new Function<Integer, Employee>() {
@Override
public Employee apply(Integer integer) {
return new Employee(integer);
}
};
System.out.println(fun.apply(1000));
System.out.println("*****************************************");
Function<Integer,Employee> fun1 = id -> new Employee(id);
Employee employee1 = fun1.apply(1001);
System.out.println(employee1);
System.out.println("********************************************");
Function<Integer,Employee> fun2 = Employee::new;
Employee employee2 = fun2.apply(1002);
System.out.println(employee2);
}
//兩個引數
//BiFunction中的R apply(T t,U u)
@Test
public void test3(){
BiFunction<Integer,String,Employee> bifun1 = new BiFunction<Integer, String, Employee>() {
@Override
public Employee apply(Integer id, String name) {
return new Employee(id,name);
}
};
System.out.println(bifun1.apply(1001,"Tom"));
System.out.println("**************************************");
BiFunction<Integer,String,Employee> bifun2 = (id,name)->new Employee(id,name);
System.out.println(bifun1.apply(1002,"Jack"));
System.out.println("****************************************");
BiFunction<Integer,String,Employee> bifun3 = Employee::new;
System.out.println(bifun1.apply(1003,"Jerry"));
}
//陣列參考
//Function中的R apply(T t)
@Test
public void test4(){
Function<Integer,String[]> fun1 = new Function<Integer, String[]>() {
@Override
public String[] apply(Integer length) {
return new String[length];
}
};
String[] arr1 = fun1.apply(4);
System.out.println(Arrays.toString(arr1));
System.out.println("**************************");
Function<Integer,String[]> fun2 = length -> new String[length];
String[] arr2 = fun2.apply(4);
System.out.println(Arrays.toString(arr2));
System.out.println("**************************");
Function<Integer,String[]> fun3 = String[] :: new;
String[] arr3 = fun3.apply(4);
System.out.println(Arrays.toString(arr3));
}
}
強大的Stream API




創建Stream的方式





import java2.Employee;
import java2.EmployeeData;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.stream.IntStream;
import java.util.stream.Stream;
/**
1、Stream 關注的是對資料的運算,與CPU打交道
集合關注的是資料的存盤,與記憶體打交道
2、
①Stream 自己不會存盤元素,
②Stream 不會改變源物件,相反,他們會回傳一個持有結果的新Stream,
③Stream 操作是延遲執行的,這意味著他們會等到需要結果的時候才執行,
3、Stream 執行流程
①Stream 的實體化
②一系列的中間操作(過濾、映射、,,,)
③終止操作
4、
4.1、一個中間操作鏈,對資料源的資料進行處理
4.2、一旦執行終止操作,就執行中間操作鏈,并產生結果,之后,不會再被使用
*/
//測驗 Stream 的實體化
public class StreamAPITest {
//創建 Stream方式一:通過集合
@Test
public void test1(){
List<Employee> employees = EmployeeData.getEmployees();
//default Stream<E> stream() : 回傳一個 順序流
Stream<Employee> stream = employees.stream();//獲取順序流
//default Stream<E> parallelStream() : 回傳一個 并行流
Stream<Employee> parallelStream = employees.parallelStream();//獲取并行流
}
//創建 Stream方式二:通過陣列
@Test
public void test2(){
int[] arr = new int[]{1,2,3,4,};
//Arrays 的靜態方法 stream() 可以獲取陣列流: static <T> Stream<T> stream(T[] array): 回傳一個流
IntStream stream1 = Arrays.stream(arr);
Employee e1 = new Employee(1001,"Tom");
Employee e2 = new Employee(1002,"Jerry");
Employee[] arr1 = new Employee[]{e1,e2};
Stream<Employee> stream2 = Arrays.stream(arr1);
}
//創建 Stream方式三:通過Stream的of()
@Test
public void test3(){
//可以呼叫Stream類靜態方法 of() : public static<T> Stream<T> of(T... values) : 回傳一個流
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);
}
//創建 Stream方式四:創建無限流
@Test
public void test4(){
//可以使用靜態方法 Stream.iterate() 和 Stream.generate(),創建無限流,
//? 迭代
//public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
//遍歷前10個偶數
Stream.iterate(0,t->t+2).limit(10).forEach(System.out::println);
//? 生成
//public static<T> Stream<T> generate(Supplier<T> s)
Stream.generate(Math::random).limit(10).forEach(System.out::println);
}
}
Stream的中間操作
篩選與切片

//1-篩選與切片
@Test
public void test1(){
List<Employee> list = EmployeeData.getEmployees();
// for (Employee e: list) {
// System.out.println(e);
// }
/*
Employee{id=1001, name='馬化騰', age=34, salary=6000.38}
Employee{id=1002, name='馬云', age=12, salary=9876.12}
Employee{id=1003, name='劉強東', age=33, salary=3000.82}
Employee{id=1004, name='雷軍', age=26, salary=7657.37}
Employee{id=1005, name='李彥宏', age=65, salary=5555.32}
Employee{id=1006, name='比爾蓋茨', age=42, salary=9500.43}
Employee{id=1007, name='任正非', age=26, salary=4333.32}
Employee{id=1008, name='扎克伯格', age=35, salary=2500.32}
*/
//filter(Predicate p)--接收 Lambda ,從流中排除某些元素,
Stream<Employee> stream = list.stream();
//練習:查詢員工表中薪資大于7000的員工資訊
stream.filter(e -> e.getSalary()>7000).forEach(System.out::println);
System.out.println("*****************************");
//limit(n)--截斷流,使其元素不超過給定數量
//練習:輸出表中的前三條資料
//【注】stream 與 iterator 類似,每呼叫一次就要重新生成
list.stream().limit(3).forEach(System.out::println);
System.out.println("*******************************");
//skip(n)--跳過元素,回傳一個扔掉了前 n 個元素的流,若流中元素不足n個,則回傳一個空流(即跳過前面幾個資料)
//跳過前面3個資料
list.stream().skip(3).forEach(System.out::println);
System.out.println();
list.stream().skip(30).forEach(System.out::println);
System.out.println("*******************************");
//distinct()--篩選,通過流所生成元素的 hashCode() 和 equals() 去除重復元素(多個重復資料只保留一個)
list.add(new Employee(1010,"劉強東",40,8000));
list.add(new Employee(1010,"劉強東",40,8000));
list.add(new Employee(1010,"劉強東",40,8000));
// System.out.println(list);
list.stream().distinct().forEach(System.out::println);
}
映射

//映射
@Test
public void test2(){
//map(Function f)
//接收一個函式作為引數,該函式會被應用到每個元素上,并將其映射成一個新的元素,即利用函式的規則對每個元素進行加工,回傳新的元素值
List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
list.stream().map(str->str.toUpperCase()).forEach(System.out::println);
System.out.println();
//練習1:獲取員工姓名長度大于3的員工姓名
List<Employee> employees = EmployeeData.getEmployees();
employees.stream().map(e->e.getName()).filter(e->e.length()>3).forEach(System.out::println);
// e是Employee物件 e是String
//練習2:
Stream<Stream<Character>> streamStream = list.stream().map(StreamAPITest1::fromStringToStream);
streamStream.forEach(s->{
s.forEach(System.out::println);
});
System.out.println("*********************************");
//mapToDouble(ToDoubleFunction f)
//接收一個函式作為引數,該函式會被應用到每個元素上,產生一個新的 DoubleStream,
//mapToInt(ToIntFunction f)
//接收一個函式作為引數,該函式會被應用到每個元素上,產生一個新的 IntStream,
//mapToLong(ToLongFunction f)
//接收一個函式作為引數,該函式會被應用到每個元素上,產生一個新的 LongStream,
//flatMap(Function f)
//接收一個函式作為引數,將流中的每個值都換成另一個流,然后把所有流連接成一個流
Stream<Character> characterStream = list.stream().flatMap(StreamAPITest1::fromStringToStream);
characterStream.forEach(System.out::println);
}
//將字串中的多個字符構成的集合轉換為對應的Stream的實體
public static Stream<Character> fromStringToStream(String str){
ArrayList<Character> list = new ArrayList<>();
for (Character c: str.toCharArray()) {
list.add(c);
}
return list.stream();
}
排序

//排序
@Test
public void test3(){
//sorted() : 自然排序
List<Integer> list = Arrays.asList(12, 36, 45, 12, 45, 1, 5, 45, 1, 3);
list.stream().sorted().forEach(System.out::println);
//拋例外,原因:Employee 沒有實作 Comparator 介面
// List<Employee> employees = EmployeeData.getEmployees();
// employees.stream().sorted().forEach(System.out::println);
//sorted(Comparator com) : 定制排序
List<Employee> employees = EmployeeData.getEmployees();
employees.stream().sorted((e1,e2)->e1.getName().compareTo(e2.getName())).forEach(System.out::println);
}
Stream的終止操作


//查找與匹配
@Test
public void test1(){
List<Employee> employees = EmployeeData.getEmployees();
//allMatch(Predicate p) 檢查是否匹配 所有 元素
//練習:是否所有員工的年齡都大于18
boolean allMatch = employees.stream().allMatch(e -> e.getAge() > 18);
System.out.println(allMatch);
//anyMatch(Predicate p) 檢查是否至少匹配 一個 元素
//練習:是否存在員工的工資大于1000
boolean anyMatch = employees.stream().anyMatch(e -> e.getSalary() > 10000);
System.out.println(anyMatch);
//noneMatch(Predicate p) 檢查是否沒有匹配所有元素
練習:是否存在員工姓”雷“
boolean noneMatch = employees.stream().noneMatch(e -> e.getName().startsWith("雷"));
System.out.println(noneMatch);
//findFirst() 回傳第一個元素
Optional<Employee> first = employees.stream().findFirst();
System.out.println(first);
//findAny() 回傳當前流中的任意元素
Optional<Employee> any = employees.parallelStream().findAny();
System.out.println(any);
//count() 回傳流中元素總數
//員工工資大于5000的人數
long count = employees.stream().filter(e -> e.getSalary() > 5000).count();
System.out.println(count);
//max(Comparator c) 回傳流中最大值
//練習:回傳最高的工資
Optional<Double> maxSalary = employees.stream().map(e -> e.getSalary()).max(Double::compare);
System.out.println(maxSalary);
//min(Comparator c) 回傳流中最小值
//回傳最低工資的員工
Optional<Employee> minSalary = employees.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
System.out.println(minSalary);
//forEach(Consumer c)內部迭代(使用 Collection 介面需要用戶去做迭代,稱為外部迭代,相反,Stream API 使用內部迭代——它幫你把迭代做了)
employees.stream().forEach(System.out::println);
}

//歸約
@Test
public void test2(){
//reduce(T iden, BinaryOperator b) 可以將流中元素反復結合起來,得到一個值,回傳 T
//練習1:計算 1-10 的自然數之和
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
Integer sum = list.stream().reduce(0, Integer::sum);//identity:初始值
System.out.println(sum);
//reduce(BinaryOperator b) 可以將流中元素反復結合起來,得到一個值,回傳 Optional<T>
//練習2:計算公司所有員工的工資總和
List<Employee> employees = EmployeeData.getEmployees();
// Optional<Double> sumMoney = employees.stream().map(e -> e.getSalary()).reduce(Double::sum);
Stream<Double> salaryStream = employees.stream().map(Employee::getSalary);
Optional<Double> sumMoney = salaryStream.reduce((d1, d2) -> d1 + d2);
System.out.println(sumMoney);
}

//收集
@Test
public void test3(){
//collect(Collector c)將流轉換為其他形式,接收一個 Collector介面的實作,用于給Stream中元素做匯總的方法.
//練習1:查找工資大于6000的員工,回傳為一個 List 或 Set
List<Employee> employees = EmployeeData.getEmployees();
List<Employee> list = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toList());
list.forEach(System.out::println);
System.out.println();
Set<Employee> set = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toSet());
set.forEach(System.out::println);
}


Optional類


/*
Optional 類:為了在程式中避免出現空指標例外出現而創建的
常見的方法 : ofNullable(T t)
orElse(T other)
*/
public class OptionalTest {
/*
? Optional.of(T t) : 創建一個 Optional 實體,t必須非空;
? Optional.empty() : 創建一個空的 Optional 實體
? Optional.ofNullable(T t):t可以為null
*/
@Test
public void test1(){
Girl girl = new Girl();
//of(T t) : 保證t是非空的
// girl=null;//girl 必須是非空的否則報例外 java.lang.NullPointerException
Optional<Girl> optionalGirl = Optional.of(girl);
}
@Test
public void test2(){
Girl girl = new Girl();
//ofNullable(T t): t可以為空null
girl=null;
Optional<Girl> optionalGirl = Optional.ofNullable(girl);
System.out.println(optionalGirl);//Optional[Girl{name='null'}] Optional.empty
//orElse(T t) : 如果當前的 Optional 內部封裝的t是非空的,則回傳內部的t
//如果內部的t是空的,則回傳orElse()方法中的引數
Girl girl1 = optionalGirl.orElse(new Girl("趙麗穎"));
System.out.println(girl1);
}
public String getGirlName(Boy boy){
return boy.getGirl().getName();//容易出現空指標例外
}
@Test
public void test3(){
Boy boy = new Boy();
String girlName = getGirlName(boy);
System.out.println(girlName);
}
//優化以后個 getGirlName() 方法 :
public String getGirlName1(Boy boy){
if (boy != null) {
Girl girl = boy.getGirl();
if (girl != null) {
return girl.getName();
}
}
return null;
}
@Test
public void test4(){
Boy boy = new Boy();
String girlName = getGirlName1(boy);
System.out.println(girlName);
}
//使用 Optional 類的 getGirlName() 方法 :
public String getGirlName2(Boy boy){
Optional<Boy> boyOptional = Optional.ofNullable(boy);
Boy boy1 = boyOptional.orElse(new Boy(new Girl("迪麗熱巴")));
//此時boy1一定非空
Girl girl = boy1.getGirl();
Optional<Girl> girlOptional = Optional.ofNullable(girl);
Girl girl1 = girlOptional.orElse(new Girl("古力娜扎"));
//此時girl1一定非空
return girl1.getName();
}
@Test
public void test5(){
Boy boy =null;
boy = new Boy();
boy = new Boy(new Girl("王菲"));
String girlName = getGirlName2(boy);
System.out.println(girlName);
}
}


轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/374704.html
標籤:其他
上一篇:淺談媒體查詢
下一篇:Charles實作mock的方法
