原文鏈接http://zhhll.icu/2020/05/11/java%E5%9F%BA%E7%A1%80/java8/java%E5%9F%BA%E7%A1%80%E4%B9%8B%E5%87%BD%E6%95%B0%E5%BC%8F%E7%BC%96%E7%A8%8B/
函式式編程
函式式編程強加了額外的約束,即所有資料必須是不可變的:設定一次,永不改變,將值傳遞給函式,該函式然后生成新值但從不修改自身外部的任何東西,不可變物件和無副作用范式解決了并發編程中最基本和最棘手的問題之一,
Lambda運算式只支持函式式介面,也就是只有一個抽象方法的介面
普通用法和函式式編程對比
@FunctionalInterface //用于判斷是否符合函式式介面
public interface Interf {
String f(String msg);
}
public class InterfImpl implements Interf {
@Override
public String f(String msg) {
return msg + " 普通實作";
}
static String func(String msg) {
return msg + " 方法參考";
}
public static void main(String[] args) {
Interf[] interfs = new Interf[]{
new InterfImpl(),//普通實作
new Interf() {
@Override
public String f(String msg) {
return msg + " 匿名內部類";
}
},//匿名內部類
msg -> msg + " lambda", //lambda運算式
InterfImpl::func //方法參考
};
for(Interf interf : interfs){
System.out.println(interf.f("測驗lambda"));
}
}
}
lambda運算式
lambda運算式,由箭頭->分隔開引數和函式體,箭頭左邊是引數,右邊是lambda回傳的運算式,即函式體
lambda運算式就是函式式介面的實體
- 當只有一個引數,可以不用括號()
- 如果沒有引數,必須使用()表示空引數串列
- 對于多個引數,將引數串列放在括號()中
- 如果有多行,需要將這些行放在花括號,在這種情況下,需要使用return
四個內置函式式介面
Consumer 消費型介面
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
public static void testConsumer(){
Consumer<Double> consumer = d -> System.out.println("花費"+d+"元");
consumer.accept(1000d);
}
Supplier 供給型介面
@FunctionalInterface
public interface Supplier<T> {
T get();
}
public static void testSupplier(){
Supplier<Integer> supplier = () -> {
return 100;
};
System.out.println(supplier.get());
}
Function 函式型介面
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
public static void testFunction(){
Function<Integer,Integer> function = x -> {
return x*100;
};
System.out.println(function.apply(10));
}
Predicate 斷言型介面
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate<T> negate() {
return (t) -> !test(t);
}
default Predicate<T> or(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
public static void testPredicate(){
Predicate<String> predicate = x -> {
return "yes".equals(x);
};
System.out.println(predicate.test("no"));
}
遞回
遞回的Lambda運算式,遞回方法必須是實體變數或靜態變數,
計算階乘
@FunctionalInterface
public interface IntCall {
int call(int i);
}
public class Recursion {
private IntCall intCall;
public static void main(String[] args) {
Recursion recursion = new Recursion();
recursion.intCall = n -> n == 0 ? 1 : n * recursion.intCall.call(n - 1);
for (int i = 0; i < 10; i++)
System.out.println(i+"! = "+recursion.intCall.call(i));
}
}
方法參考
java8的方法參考,由::區分,在::左邊是類或物件的名稱,在::的右邊是方法的名稱,但是沒有引數串列
如果lambda體的內容有方法已經實作了,可以使用方法參考
方法參考其實也是lambda運算式,要求介面中的抽象方法的形參串列和回傳值型別與方法參考的方法的形參串列和回傳值型別相同
三種語法格式
1、物件::實體方法
2、類::靜態方法
3、類::實體方法 當lambda運算式第一個引數是實體方法的呼叫者,第二個引數是實體方法的引數時,可以使用
public class TestMethodRef {
/**
* 物件::實體方法
*/
public static void test1(){
Consumer<String> con = System.out::println;
con.accept("aaaa");
}
/**
* 類::靜態方法
*/
public static void test2(){
Consumer<String> con = TestMethodRef::testStatic;
con.accept("xxxx");
}
/**
* 類::實體方法
*/
public static void test3(){
MyTest myTest = String::equals;
}
/**
* 測驗無參構造器
* @return
*/
public static TestMethodRef test4(){
Supplier<TestMethodRef> supplier = TestMethodRef::new;
return supplier.get();
}
/**
* 測驗有參構造器
* @return
*/
public static TestMethodRef test5(){
Function<Integer,TestMethodRef> function = TestMethodRef::new;
return function.apply(10);
}
public TestMethodRef(){
System.out.println("無參構造器呼叫");
}
private int x;
public TestMethodRef(int x){
this.x = x;
}
public static void main(String[] args) {
test1();
test2();
test3();
test4();
TestMethodRef t = test5();
System.out.println(t.x);
}
public static void testStatic(String x){
System.out.println("我輸出入了"+x);
}
}
@FunctionalInterface
interface MyTest{
boolean test(String x,String y);
}
由于本身的博客百度沒有收錄,博客地址http://zhhll.icu
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/249324.html
標籤:Java
下一篇:資料庫三范式和反三范式
