函数式编程强加了额外的约束,即所有数据必须是不可变的:设置一次,永不改变。将值传递给函数,该函数然后生成新值但从不修改自身外部的任何东西,不可变对象和无副作用范式解决了并发编程中最基本和最棘手的问题之一。
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表达式就是函数式接口的实例
定义了一个accept方法,如果需要访问类型T的对象,并对其执行某些操作,可以使用这个接口
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer andThen(Consumer super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
public static void testConsumer(){
Consumer consumer = d -> System.out.println("花费"+d+"元");
consumer.accept(1000d);
}
@FunctionalInterface
public interface Supplier<T> {
T get();
}
public static void testSupplier(){
Supplier supplier = () -> {
return 100;
};
System.out.println(supplier.get());
}
定义了一个apply方法,如果将输入对象的信息映射到输出,可以使用该接口
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
default Function compose(Function super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default Function andThen(Function super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static Function identity() {
return t -> t;
}
}
public static void testFunction(){
Function function = x -> {
return x*100;
};
System.out.println(function.apply(10));
}
定义了一个test方法,当需要使用布尔表达式时可以使用该接口
@FunctionalInterface
public interface Predicate<T> {
boolean test(T t);
default Predicate and(Predicate super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
default Predicate negate() {
return (t) -> !test(t);
}
default Predicate or(Predicate super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}
static Predicate isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
}
public static void testPredicate(){
Predicate 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体的内容有方法已经实现了,可以使用方法引用
Apple::getWeight 该表示方式其实是 (Apple a) -> a.getWeight()的快捷写法
方法引用其实也是lambda表达式,要求接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型相同
三种语法格式 1、对象::实例方法,指向现有对象的实例方法引用 2、类::静态方法,指向静态方法的方法引用 3、类::实例方法,指向任意类型实例方法的方法引用 当lambda表达式第一个参数是实例方法的调用者,第二个参数是实例方法的参数时,可以使用
public class TestMethodRef {
/**
* 对象::实例方法
*/
public static void test1(){
Consumer con = System.out::println;
con.accept("aaaa");
}
/**
* 类::静态方法
*/
public static void test2(){
Consumer con = TestMethodRef::testStatic;
con.accept("xxxx");
}
/**
* 类::实例方法
*/
public static void test3(){
MyTest myTest = String::equals;
}
/**
* 测试无参构造器
* @return
*/
public static TestMethodRef test4(){
Supplier supplier = TestMethodRef::new;
return supplier.get();
}
/**
* 测试有参构造器
* @return
*/
public static TestMethodRef test5(){
Function 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);
}
https://zhhll.icu/2020/java基础/java8/2.java基础之函数式编程/
本文由 mdnice 多平台发布