一、FunctionInterface 是什麼?和Lambda表達式有什麼關係?java
package com.wood.functional;
/**
* @Description: 函數式接口
* @Author wood
* @Date 2019-08-15
*
* @FunctionalInterface 聲明一個接口是函數式接口,目的是能夠用lambda表達式的方式實現接口
* 函數式接口只能包含一個抽象方法,重寫父類的方法不算
* Java中全部的對象都是繼承自Object,因此MyInterface其實是繼承自Object,因此有toString()
*
* 在將函數做爲一等公民的語言(JavaScript、Python)中,Lambda表達式(匿名函數、閉包)是函數,
* 但在Java中,Lambda表達式是對象(Java中一切皆對象),必須依附於一類特別的對象FunctionalInterface
*
* JDK8強調傳遞行爲,而不單單是數據
*
*/
@FunctionalInterface
public interface MyInterface {
// 函數式接口只能包含一個抽象方法
void test();
// 重寫父類(Object)的方法不算,因此可以編譯經過
String toString();
}
package com.wood.functional;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @Description: 測試函數式接口
* @Author wood
* @Date 2019-08-15
*/
public class MyTest {
public void testInterface(MyInterface myInterface) {
myInterface.test();
}
public static void main(String[] args) {
MyTest myTest = new MyTest();
myTest.testInterface(new MyInterface() {
@Override
public void test() {
System.out.println("調用函數式接口test():經過new MyInterface()的方式");
}
});
myTest.testInterface(() -> System.out.println("調用函數式接口test():經過lambda表達式的方式"));
MyInterface myInterface = () -> {
System.out.println("這是MyInterface的實現,是一個匿名函數");
};
myTest.testInterface(myInterface);
}
}
二、FunctionInterface函數式接口強調傳遞的是行爲,不是數據。閉包
package com.wood.functional;
import java.util.Arrays;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* @Description: 測試函數式接口
* @Author wood
* @Date 2019-08-15
*/
public class MyTest {
public void testInterface(MyInterface myInterface) {
myInterface.test();
}
public static void main(String[] args) {
MyTest myTest = new MyTest();
myTest.testInterface(new MyInterface() {
@Override
public void test() {
System.out.println("調用函數式接口test():經過new MyInterface()的方式");
}
});
myTest.testInterface(() -> System.out.println("調用函數式接口test():經過lambda表達式的方式"));
MyInterface myInterface = () -> {
System.out.println("這是MyInterface的實現,是一個匿名函數");
};
myTest.testInterface(myInterface);
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
/**
* JDK8開始,接口能夠有默認實現,用default關鍵字修飾
* default void forEach(Consumer<? super T> action) {
* Objects.requireNonNull(action);
* for (T t : this) {
* action.accept(t);
* }
* }
* */
list.forEach(new Consumer<Integer>() {
@Override
public void accept(Integer integer) {
System.out.println(integer);
}
});
// 方法引用
list.forEach(System.out::println);
/**
* JDK8強調傳遞行爲,而不單單是數據
* */
System.out.println("-----JDK8強調傳遞行爲,而不單單是數據-----");
System.out.println(myTest.calculate(2, t -> 2 * t));
System.out.println(myTest.calculate(2, t -> t * t));
System.out.println(myTest.calculate(2, t -> t + 1));
System.out.println("-----compose-----(先執行t -> t + 1 再執行t -> 2 * t)");
System.out.println(myTest.compose(2, t -> 2 * t, t -> t + 1)); // 6
System.out.println("-----andThen-----(先執行t -> 2 * t 再執行t -> t + 1)");
System.out.println(myTest.andThen(2, t -> 2 * t, t -> t + 1)); // 5
System.out.println("-----BiFunction是Function的加強形式-----");
/**
* 若是是JDK7傳統的作法是,須要寫4個方法(加、減、乘、除)
* 而JDK8能夠藉助於BiFunction來完成,傳遞的是行爲
* */
System.out.println(myTest.biFunction(1, 2, (t1, t2) -> t1 + t2));
System.out.println(myTest.biFunction(1, 2, (t1, t2) -> t1 - t2));
System.out.println(myTest.biFunction(1, 2, (t1, t2) -> t1 * t2));
System.out.println(myTest.biFunction(1, 2, (t1, t2) -> t1 / t2));
System.out.println("-----biFunction andThen-----(先執行(t1, t2) -> t1 + t2 再執行t -> t * t)");
System.out.println(myTest.biFunctionAndThen(1, 2, (t1, t2) -> t1 + t2, t -> t * t)); // 9
// stream獲取流並對流操做,操做完成後再將它轉換爲集合
System.out.println(list.stream().filter(t -> t > 2).collect(Collectors.toList()));
// 原來的集合不變,流操做返回的是新集合
System.out.println(list);
System.out.println(myTest.biFunctionFilter(3, list, (value, integerList) -> integerList.stream().filter(t -> t > value).collect(Collectors.toList())));
}
/**
* 計算
* 高階函數:如何一個方法接收一個函數做爲參數或返回值是一個函數
* @param t 輸入值
* @param function 對t執行的行爲函數,Function<Integer(輸入類型), Integer(輸出類型)>
* @return 操做後的值
*/
public int calculate(int t, Function<Integer, Integer> function) {
return function.apply(t);
}
public int compose(int t, Function<Integer, Integer> function1, Function<Integer, Integer> function2) {
// 先執行function2的行爲,再執行function1的行爲
return function1.compose(function2).apply(t);
}
public int andThen(int t, Function<Integer, Integer> function1, Function<Integer, Integer> function2) {
// function1 -> function2
return function1.andThen(function2).apply(t);
}
public int biFunction(int t1, int t2, BiFunction<Integer, Integer, Integer> biFunction) {
// BiFunction<A, B, Integer> biFunction 對入參A、B執行biFunction行爲返回Integer類型的值
// Function是一個輸入,BiFunction是兩個輸入
return biFunction.apply(t1, t2);
}
public int biFunctionAndThen(int t1, int t2, BiFunction<Integer, Integer, Integer> biFunction, Function<Integer, Integer> function) {
// andThen表示先執行biFunction,再執行function
return biFunction.andThen(function).apply(t1, t2);
}
public List<Integer> biFunctionFilter(int t, List<Integer> list, BiFunction<Integer, List<Integer>, List<Integer>> biFunction) {
return biFunction.apply(t, list);
}
}
三、Predicate是什麼?如何應用?
public List<Integer> conditionFilter(List<Integer> list, Predicate<Integer> predicate) {
return list.stream().filter(predicate).collect(Collectors.toList());
}public List<Integer> conditionAndFilter(List<Integer> list, Predicate<Integer> predicate1, Predicate<Integer> predicate2) {
return list.stream().filter(predicate1.and(predicate2)).collect(Collectors.toList());
}
// Predicate表示斷言條件,給定輸入判斷是否符合條件
System.out.println("-----Predicate斷言條件-----");
Predicate<Integer> predicate = t -> t > 2;
System.out.println(predicate.test(3));
System.out.println("-----給定輸入和條件,輸出想要的數據-----");
System.out.println(myTest.conditionFilter(list, t -> t > 2));
System.out.println(myTest.conditionFilter(list, t -> t % 2 == 0));
System.out.println(myTest.conditionFilter(list, t -> t % 2 == 1));
System.out.println(myTest.conditionFilter(list, t -> true));
System.out.println(myTest.conditionFilter(list, t -> false));
System.out.println("多個Predicate執行and操做,也就是多個條件 && ==> t > 2 && t % 2 == 0");
System.out.println(myTest.conditionAndFilter(list, t -> t > 2, t -> t % 2 == 0));
四、Supplier是什麼?app
/**
* Supplier 不接收參數,返回一個對象
* Gets a result
* T get ();
* */
Supplier<Student> supplier = () -> new Student("小伍", 20);
System.out.println(supplier.get().toString());
五、可選類型Optionalide
package com.wood.functional;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
/**
* @Description: 可選類型Optional
* @Author wood
* @Date 2019-08-18
*/
public class OptionalTest {
/**
* 可選類型Optional被設計用來防止空指針異常NullPointerException
* */
public static void main(String[] args) {
Optional<String> optional = Optional.of("hello");
// 若是對象存在就打印
if (optional.isPresent()) {
System.out.println(optional.get());
}
// 推薦的optional的使用方式
optional.ifPresent(System.out::println);
optional = Optional.empty();
System.out.println(optional.orElse("若是optional是空則輸出這句話"));
System.out.println(optional.orElseGet(() -> "若是optional是空,則經過Supplier獲取值"));
/**
* Optional具體應用
* */
Student student1 = new Student("小伍", 18);
Student student2 = new Student("馬拉松", 100);
List<Student> list = Arrays.asList(student1, student2);
Optional<Student> optionalStudent = Optional.ofNullable(student2);
System.out.println(optionalStudent.map(student -> student.getAge() > 50 ? student : null).orElse(student1));
}
}
六、方法引用(函數指針)函數
package com.wood.functional;
/**
* @Description: 學生
* @Author wood
* @Date 2019-08-18
*/
public class Student {
private String name;
private int age;
public Student(String name, int age) {
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
/**
* 靜態方法,能夠用來作方法應用 Student::desc
* @param student
*/
public static void desc(Student student) {
String desc = "學生{" +
"姓名='" + student.getName() + '\'' +
", 年齡=" + student.getAge() +
'}';
System.out.println(desc);
}
}
/**
* Optional具體應用
* */
Student student1 = new Student("小伍", 18);
Student student2 = new Student("馬拉松", 100);
List<Student> list = Arrays.asList(student1, student2);
Optional<Student> optionalStudent = Optional.ofNullable(student2);
System.out.println(optionalStudent.map(student -> student.getAge() > 50 ? student : null).orElse(student1));
/**
* 方法引用(函數指針)
* public static void desc(Student student) { ... }
* 類名::靜態方法
* */
list.forEach(student -> Student.desc(student));
list.forEach(Student::desc);