Java 8函数式编程梳理

默认方法

可以给接口添加一个默认的实现方法,优点,针对现有的接口,如List,我们可以偷偷的添加新的方法,这样可以达到一种兼容目的

实例

public interface A {
	default void print() {
		System.out.println("A.print()");
	}
}
public interface B {
	default void print() {
		System.out.println("B.print()");
	}
}

C类直接实现默认接口

public class C implements A, B {

	// 这里的重写是因为方法冲突,正常情况是不需要重写的
	@Override
	public void print() {
		A.super.print();
		B.super.print();
	}
	
	public static void main(String[] args) {
		A a = new C();
		a.print();
	}

}

默认方法还有一个好处就是给一个现有类添加一个方法十分方便,直接implements即可

静态默认方法

使用上与嵌套类相似,可做工具类使用

定义

public interface D {
	public static void print() {
		System.out.println("D.print()");
	}
}

使用

public class DTest {
	public static void main(String[] args) {
		D.print();
	}
}

Lambda 表达式

将函数作为参数传递进方法中

例子一

定义一个接口,实现接口

public interface Calc {
	String operate(int x, int y);
}

public class CalcImpl implements Calc {

	@Override
	public String operate(int x, int y) {
		return x + y + " - end";
	}

}

使用接口


public class Controller {
	public void print(int x, int y) {
		Calc calc = new CalcImpl();
		String result = calc.operate(x, y);
		System.out.println("start - " + result);
	}
}

测试接口

public class TestRun {

	public static void main(String[] args) {
		Controller controller = new Controller();
		controller.print(10, 20);
	}

}

上述接口使用与实现绑定,高耦合,改造一下代码

例子二

将接口当做入参传入

public class Controller {
	public void print(int x, int y, Calc calc) {
		String result = calc.operate(x, y);
		System.out.println("start - " + result);
	}
}

测试代码,将具体的实现逻辑放入使用方法之外,这样如果有新的计算,可以实现热绑定,低耦合

public class TestRun {
	public static void main(String[] args) {
		Calc calc = new CalcImpl();
		Controller controller = new Controller();
		controller.print(10, 20, calc);
	}
}

例子三

匿名内部类的引用,重新实现一种计算方法

public class TestRun {

	public static void main(String[] args) {
		Calc calc = new Calc() {
			@Override
			public String operate(int x, int y) {
				return x + y + "";
			}
		};
		Controller controller = new Controller();
		controller.print(10, 20, calc);
	}

}

以上代码也等价于下面代码

public class TestRun {

	public static void main(String[] args) {
		Controller controller = new Controller();
		controller.print(10, 20, new Calc() {
			@Override
			public String operate(int x, int y) {
				return x + y + "";
			}
		});
	}

}

new Calcoperate等信息我们可以去掉,这时,我们可以引入Lambda 表达式。简化如下

public class TestRun {

	public static void main(String[] args) {
		Controller controller = new Controller();
		controller.print(10, 20, (int x, int y) -> {
				return x + y + "";
			}
		);
	}

}

甚至我们还可以把入参类型,返回关键字return去掉,如下

public class TestRun {

	public static void main(String[] args) {
		Controller controller = new Controller();
		controller.print(10, 20, (x,y) -> x + y + "");
	}

}
语法

lambda 表达式的语法格式如下:

(parameters) -> expression
或
(parameters) ->{ statements; }
  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。
  • 可选的大括号:如果主体包含了一个语句,就不需要使用大括号。
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

注意点一,Lambda定义一个接口只允许有一个方法,定义超过一个使用Lambda接口会提示错误,如下所示

public interface Calc {
	String operate(int x, int y);
	void print();
}

在这里插入图片描述

可强制约束定义,加上@FunctionalInterface注解生声明定义

@FunctionalInterface
public interface Calc {
	String operate(int x, int y);
}

方法引用

方法引用是将方法传入给lambda方法,可支持以下三种

  1. 构造器
  2. 对象方法
  3. 静态方法

定义一个类

public class Deal {
	public void repair() {
        System.out.println("Repaired ");
    }
	public void repair2222() {
		System.out.println("Repaired 2222");
	}
	public void repair6666() {
		System.out.println("Repaired 6666");
	}
}

定义两个函数式接口参数,其中Consumer,Supplier都是JDK提供的

public class MyTest {
	
	public void doTryClass(Consumer<Deal> action) {
		Deal deal = new Deal();
		action.accept(deal);
	}
	
	public void doTryClass(Supplier<Deal> supplier) {
		Deal deal = supplier.get();
		deal.repair();
	}
}

静态调用

public class DealStatic {
	public static void saymmp(Deal deal) {
		System.out.println("===");
		deal.repair6666();
		System.out.println("===");
	}
}

调用测试

public class OtherTest {
	public static void main(String[] args) {
		MyTest test = new MyTest();
		
		// 消费自身的方法可以不传参数
		test.doTryClass(Deal::repair);
		test.doTryClass(Deal::repair2222);
		test.doTryClass(Deal::repair6666);
		
		// 静态方法(传入参数必须与Consumer泛型参数Deal一致)
		test.doTryClass(DealStatic::saymmp);
		
		// 非静态方法需要先实例化,再引用
		DealNonStatic nonDeal = new DealNonStatic();
		test.doTryClass(nonDeal::test);
		
		// 构造器
		test.doIt4getClass(Deal::new);
	}
}

测试结果

Repaired 
Repaired 2222
Repaired 6666
===
Repaired 6666
===
===non
Repaired 6666
===non
Repaired 

java 8 提供的函数式接口列表

以下仅供参考

函数式接口描述
BiConsumer<T,U>代表了一个接受两个输入参数的操作,并且不返回任何结果
BiFunction<T,U,R>代表了一个接受两个输入参数的方法,并且返回一个结果
BinaryOperator<T>代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果
BiPredicate<T,U>代表了一个两个参数的boolean值方法
BooleanSupplier代表了boolean值结果的提供方
Consumer<T>代表了接受一个输入参数并且无返回的操作
DoubleBinaryOperator代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。
DoubleConsumer代表一个接受double值参数的操作,并且不返回结果。
DoubleFunction<R>代表接受一个double值参数的方法,并且返回结果
DoublePredicate代表一个拥有double值参数的boolean值方法
DoubleSupplier代表一个double值结构的提供方
DoubleToIntFunction接受一个double类型输入,返回一个int类型结果。
DoubleToLongFunction接受一个double类型输入,返回一个long类型结果
DoubleUnaryOperator接受一个参数同为类型double,返回值类型也为double 。
Function<T,R>接受一个输入参数,返回一个结果。
IntBinaryOperator接受两个参数同为类型int,返回值类型也为int 。
IntConsumer接受一个int类型的输入参数,无返回值 。
IntFunction<R>接受一个int类型输入参数,返回一个结果 。
IntPredicate:接受一个int输入参数,返回一个布尔值的结果。
IntSupplier无参数,返回一个int类型结果。
IntToDoubleFunction接受一个int类型输入,返回一个double类型结果 。
IntToLongFunction接受一个int类型输入,返回一个long类型结果。
IntUnaryOperator接受一个参数同为类型int,返回值类型也为int 。
LongBinaryOperator接受两个参数同为类型long,返回值类型也为long。
LongConsumer接受一个long类型的输入参数,无返回值。
LongFunction<R>接受一个long类型输入参数,返回一个结果。
LongPredicateR接受一个long输入参数,返回一个布尔值类型结果。
LongSupplier无参数,返回一个结果long类型的值。
LongToDoubleFunction接受一个long类型输入,返回一个double类型结果。
LongToIntFunction接受一个long类型输入,返回一个int类型结果。
LongUnaryOperator接受一个参数同为类型long,返回值类型也为long。
ObjDoubleConsumer<T>接受一个object类型和一个double类型的输入参数,无返回值。
ObjIntConsumer<T>接受一个object类型和一个int类型的输入参数,无返回值。
ObjLongConsumer<T>接受一个object类型和一个long类型的输入参数,无返回值。
Predicate<T>接受一个输入参数,返回一个布尔值结果。
Supplier<T>无参数,返回一个结果。
ToDoubleBiFunction<T,U>接受两个输入参数,返回一个double类型结果
ToDoubleFunction<T>接受一个输入参数,返回一个double类型结果
ToIntBiFunction<T,U>接受两个输入参数,返回一个int类型结果。
ToIntFunction<T>接受一个输入参数,返回一个int类型结果。
ToLongBiFunction<T,U>接受两个输入参数,返回一个long类型结果。
ToLongFunction<T>接受一个输入参数,返回一个long类型结果。
UnaryOperator<T>接受一个参数为类型T,返回值类型也为T。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值