【Java8】Function函数式接口详解及使用

该文章已生成可运行项目,

【Java8】Function函数式接口详解及使用

【一】函数式接口

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

Functional Interface(功能接口)为lambda表达式和方法引用(用冒号::来进行方法的调用)提供目标类型。每个功能接口都有一个抽象方法,称为该功能接口的功能方法,lambda表达式的参数和返回类型与之匹配或适配。功能接口可以在多个上下文中提供目标类型,例如赋值上下文,方法调用或强制转换上下文:

// Assignment context
Predicate<String> p = String::isEmpty;

// Method invocation context
stream.filter(e -> e.getSize() > 10)...

// Cast context
stream.map((ToIntFunction) e -> e.getSize())...

函数式接口可以使用lambda表达式,方法引用或构造函数引用创建功能接口的实例。

Java8为函数式接口引入了一个新注解@FunctionalInterface,主要用于编译级错误检查,加上该注解,当接口不符合函数式接口定义的时候,编译器会报错。
此注解不是编译器将接口识别为功能接口的必要条件,而仅是帮助捕获设计意图并获得编译器帮助识别意外违反设计意图的帮助。

正确例子,没有报错:

@FunctionalInterface
public interface HelloWorldService {

    void sayHello(String msg);

}

错误例子,接口中包含了两个抽象方法,违反了函数式接口的定义,提示在接口中找到多个非重写的抽象方法。
在这里插入图片描述
注意: 加不加 @FunctionalInterface对于接口是不是函数式接口没有影响,该注解只是提醒编译器去检查该接口是否仅包含一个抽象方法。

【1】允许定义默认方法

函数式接口里是可以包含默认方法,因为默认方法不是抽象方法,其有一个默认实现,所以是符合函数式接口的定义的。

如下代码不会报错:

@FunctionalInterface
public interface HelloWorldService {

    void sayHello(String msg);

    default void doSomeWork1() {
        // Method body
    }

    default void doSomeWork2() {
        // Method body
    }

}

【2】允许定义静态方法

函数式接口里是可以包含静态方法,因为静态方法不能是抽象方法,是一个已经实现了的方法,所以是符合函数式接口的定义的。

如下代码不会报错:

@FunctionalInterface
public interface HelloWorldService {

    void sayHello(String msg);

    static void printHello() {
        System.out.println("Hello");
    }

}

【3】允许定义java.lang.Object的public方法

函数式接口里是可以包含Object里的public方法,这些方法对于函数式接口来说,不被当成是抽象方法(虽然它们是抽象方法);因为任何一个函数式接口的实现,默认都继承了Object类,包含了来自java.lang.Object里对这些抽象方法的实现;

如下代码不会报错:

@FunctionalInterface
public interface HelloWorldService {

    void sayHello(String msg);

	@Override
    boolean equals(Object obj);

}

【4】已有函数式接口

函数式接口可以对现有的函数友好地支持lambda。

JDK1.8之前已有的函数式接口:
java.lang.Runnable
java.util.concurrent.Callable
java.security.PrivilegedAction
java.util.Comparator
java.io.FileFilter
java.nio.file.PathMatcher
java.lang.reflect.InvocationHandler
java.beans.PropertyChangeListener
java.awt.event.ActionListener
javax.swing.event.ChangeListener

JDK1.8新增加的函数接口:
java.util.function

【二】Function函数

在这里插入图片描述

【1】Function<T, R>

在这里插入图片描述

(1)apply(T t)

Function<String, String> function = a -> a + " Jack!";
System.out.println(function.apply("Hello")); // Hello Jack!

在这里插入图片描述

import java.util.function.Function;

public class Function_Demo {
    public static void main(String[] args) {
        Function<String,String> function = new Function<String, String>() {
            @Override
            public String apply(String s) {
                return s;
            }
        };
        System.out.println(function.apply("Sky"));

        //lambda 表达式写法:
        function = ((str)->{ return str;});
        System.out.println(function.apply("Song"));
    }
}

(2)andThen(Function<? super R,? extends V> after)

Function<String, String> function = a -> a + " Jack!";
Function<String, String> function1 = a -> a + " Bob!";
String greet = function.andThen(function1).apply("Hello");
System.out.println(greet); // Hello Jack! Bob!

(3)compose(Function<? super V,? extends T> before)

Function<String, String> function = a -> a + " Jack!";
Function<String, String> function1 = a -> a + " Bob!";
String greet = function.compose(function1).apply("Hello");
System.out.println(greet); // Hello Bob! Jack!

【2】BiFunction<T, U, R>

在这里插入图片描述

(1)apply(T t, U u)

BiFunction<String, String, String> biFunction = (a, b) -> a + b;
System.out.println(biFunction.apply("Hello ", "Jack!")); // Hello Jack!

(2)andThen(Function<? super R,? extends V> after)

BiFunction<String, String, String> biFunction = (a, b) -> a + b;
Function<String, String> function = (a) -> a + "!!!";
System.out.println(biFunction.andThen(function).apply("Hello", " Jack")); // Hello Jack!!!

【3】DoubleFunction

在这里插入图片描述

(1)apply(double value)

DoubleFunction<String> doubleFunction = doub -> "结果:" + doub;
System.out.println(doubleFunction.apply(1.6)); // 结果:1.6

【4】DoubleToIntFunction

在这里插入图片描述

(1)applyAsInt(double value)

DoubleToIntFunction doubleToIntFunction = doub -> Double.valueOf(doub).intValue();
System.out.println(doubleToIntFunction.applyAsInt(1.2)); // 1

【5】ToDoubleBiFunction<T,U>

在这里插入图片描述

applyAsDouble(T t, U u)

ToDoubleBiFunction<Long, Float> toDoubleBiFunction = (lon, floa) -> lon
	.doubleValue() + floa.doubleValue();
System.out.println(toDoubleBiFunction.applyAsDouble(11L, 235.5f)); // 246.5

【6】ToDoubleFunction

在这里插入图片描述
applyAsDouble(T value)

ToDoubleFunction<Float> toDoubleFunction = floa -> floa.doubleValue();
System.out.println(toDoubleFunction.applyAsDouble(12315f)); // 12315.0

【三】Consumer消费者

在这里插入图片描述

【1】Consumer

在这里插入图片描述

(1)accept(T t)

StringBuilder sb = new StringBuilder("Hello ");
Consumer<StringBuilder> consumer = (str) -> str.append("Jack!");
consumer.accept(sb);
System.out.println(sb.toString());	// Hello Jack!

在这里插入图片描述

import java.util.function.Consumer;

public class Consumer_Demo {
    public static void main(String[] args) {
        Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println("消费:"+s);
            }
        };
        consumer.accept("cake");

        //lambda 表达式写法:
        consumer = (str)->{ System.out.println("消费:"+str); };
        consumer.accept("money");
    }

}

(2)andThen(Consumer<? super T> after)

StringBuilder sb = new StringBuilder("Hello ");
Consumer<StringBuilder> consumer = (str) -> str.append("Jack!");
Consumer<StringBuilder> consumer1 = (str) -> str.append(" Bob!");
consumer.andThen(consumer1).accept(sb);
System.out.println(sb.toString());	// Hello Jack! Bob!

【3】BiConsumer<T,U>

在这里插入图片描述

(1)accept(T t, U u)

StringBuilder sb = new StringBuilder();
BiConsumer<String, String> biConsumer = (a, b) -> {
	sb.append(a);
	sb.append(b);
};
biConsumer.accept("Hello ", "Jack!");
System.out.println(sb.toString());	// Hello Jack!

(2)andThen(BiConsumer<? super T,? super U> after)

StringBuilder sb = new StringBuilder();
BiConsumer<String, String> biConsumer = (a, b) -> {
	sb.append(a);
	sb.append(b);
};
BiConsumer<String, String> biConsumer1 = (a, b) -> {
	System.out.println(a + b);
};
biConsumer.andThen(biConsumer1).accept("Hello", " Jack!"); // Hello Jack!

【3】DoubleConsumer

在这里插入图片描述

(1)accept(double value)

DoubleConsumer doubleConsumer = System.out::println;
doubleConsumer.accept(1.3); // 1.3

(2)andThen(DoubleConsumer after)

DoubleConsumer doubleConsumer = System.out::println;
DoubleConsumer doubleConsumer1 = System.out::println;
doubleConsumer.andThen(doubleConsumer1).accept(1.3);
// 1.3  
// 1.3

【4】ObjDoubleConsumer

在这里插入图片描述
accept(T t, double value)

ObjDoubleConsumer<String> doubleConsumer = (obj, doub)
	-> System.out.println(obj + doub);
doubleConsumer.accept("金额:", 222.66); // 金额:222.66

【四】Predicate谓语

在这里插入图片描述

【1】Predicate

在这里插入图片描述

(1)test(T t)

Predicate<Integer> predicate = number -> number != 0;
System.out.println(predicate.test(10));    //true

在这里插入图片描述

import java.util.function.Predicate;

public class Predicate_demo {
    public static void main(String[] args) {
        Predicate<Integer> predicate =new Predicate<Integer>() {
            @Override
            public boolean test(Integer integer) {
                return 0 != integer;
            }
        };
        System.out.println(predicate.test(0));

        //lambda 表达式写法:
        predicate = (integer -> {return 0 != integer;});
        System.out.println(predicate.test(1));
    }
}

(2)and(Predicate<? super T> other)

Predicate<Integer> predicate = number -> number != 0;
predicate = predicate.and(number -> number >= 10);
System.out.println(predicate.test(10));    //true

(3)or(Predicate<? super T> other)

Predicate<Integer> predicate = number -> number != 0;
predicate = predicate.or(number -> number != 10);
System.out.println(predicate.test(10));    //true

(4)negate()

Predicate<Integer> predicate = number -> number != 0;
predicate = predicate.negate();
System.out.println(predicate.test(10));    //false

【2】BiPredicate<T,U>

在这里插入图片描述

(1)test(T t, U u)

BiPredicate<Integer, Integer> biPredicate = (a, b) -> !a.equals(b);
System.out.println(biPredicate.test(1, 2)); // true

(2)and(BiPredicate<? super T,? super U> other)

BiPredicate<Integer, Integer> biPredicate = (a, b) -> !a.equals(b);
biPredicate = biPredicate.and((a, b) -> a.equals(b));
System.out.println(biPredicate.test(1, 2)); // false

(3)or(BiPredicate<? super T,? super U> other)

BiPredicate<Integer, Integer> biPredicate = (a, b) -> !a.equals(b);
biPredicate = biPredicate.or((a, b) -> a == b);
System.out.println(biPredicate.test(1, 1)); // true

(4)negate()

BiPredicate<Integer, Integer> biPredicate = (a, b) -> !a.equals(b);
biPredicate = biPredicate.negate();
System.out.println(biPredicate.test(1, 2)); // false

【3】DoublePredicate

在这里插入图片描述

(1)test(double value)

DoublePredicate doublePredicate = doub -> doub != 0;
System.out.println(doublePredicate.test(10)); // true

(2)and(DoublePredicate other)

DoublePredicate doublePredicate = doub -> doub != 0;
doublePredicate = doublePredicate.and(doub -> doub < 2);
System.out.println(doublePredicate.test(1.7)); // true

(3)or(DoublePredicate other)

DoublePredicate doublePredicate = doub -> doub != 0;
doublePredicate = doublePredicate.or(doub -> doub > 2);
System.out.println(doublePredicate.test(1.7)); // true

(4)negate()

DoublePredicate doublePredicate = doub -> doub != 0;
doublePredicate = doublePredicate.negate();
System.out.println(doublePredicate.test(1.7)); // false

【五】Supplier供应商

在这里插入图片描述

【1】Supplier

在这里插入图片描述

(1)get()

Supplier<String> supplier = () -> "Hello Jack!";
System.out.println(supplier.get()); // Hello Jack!

在这里插入图片描述

import java.util.function.Supplier;

public class Supplier_Demo {
    public static void main(String[] args) {
        Supplier<String> supplier = new Supplier<String>() {
            @Override
            public String get() {
                return "提供:Sky";
            }
        };
        System.out.println(supplier.get());

        //lambda 表达式写法:
        supplier = ()->{return "提供:Song";};
        System.out.println(supplier.get());
    }
}

【2】BooleanSupplier

在这里插入图片描述

(1)getAsBoolean()

BooleanSupplier booleanSupplier = () -> true;
System.out.println(booleanSupplier.getAsBoolean()); // true

【3】DoubleSupplier

在这里插入图片描述

(1)getAsDouble()

DoubleSupplier doubleSupplier = () -> 2.7;
System.out.println(doubleSupplier.getAsDouble()); // 2.7

【六】Operator操作员

除了Function,Consumer,Predicate,Supplier这几个基本的函数形式,还有其它派生的函数形式,它们扩展了基本的函数形式,包括UnaryOperator (extends Function)和BinaryOperator (extends BiFunction)。

在这里插入图片描述

【1】UnaryOperator

在这里插入图片描述

(1)apply(T t)

UnaryOperator<String> unaryOperator = greet -> greet + " Bob!";
System.out.println(unaryOperator.apply("Hello")); // Hello Bob!

(2)andThen(Function<? super T,? extends T> after)

UnaryOperator<String> unaryOperator = greet -> greet + " Bob!";
UnaryOperator<String> unaryOperator1 = greet -> greet + " Jack!";
String greet = unaryOperator.andThen(unaryOperator1).apply("Hello");
System.out.println(greet); // Hello Bob! Jack!

(3)compose(Function<? super T,? extends T> before)

UnaryOperator<String> unaryOperator = greet -> greet + " Bob!";
UnaryOperator<String> unaryOperator1 = greet -> greet + " Jack!";
String greet = unaryOperator.compose(unaryOperator1).apply("Hello");
System.out.println(greet); // Hello Jack! Bob!

【2】BinaryOperator

在这里插入图片描述

(1)apply(T t, T u)

BinaryOperator<String> binaryOperator = (flag, flag1) -> flag + flag1;
System.out.println(binaryOperator.apply("Hello ", "Jack!")); // Hello Jack!

(2)andThen(Function<? super T,? extends T> after)

BinaryOperator<String> binaryOperator = (flag, flag1) -> flag + flag1;
Function<String, String> function = a -> a + "!!!";
System.out.println(binaryOperator.andThen(function).apply("Hello", " Jack")); // Hello Jack!!!

(3)maxBy(Comparator<? super T> comparator)

BinaryOperator<Integer> integerBinaryOperator = BinaryOperator.maxBy(Integer::compareTo);
Integer max = integerBinaryOperator.apply(12, 10);
System.out.println(max); // 12

(4)minBy(Comparator<? super T> comparator)

BinaryOperator<Integer> integerBinaryOperator1 = BinaryOperator.minBy(Integer::compare);
Integer min = integerBinaryOperator1.apply(12, 10);
System.out.println(min); // 10

【3】DoubleBinaryOperator

在这里插入图片描述

(1)applyAsDouble(double left, double right)

DoubleBinaryOperator doubleBinaryOperator = (doub1, doub2) -> doub1
	+ doub2;
System.out.println(doubleBinaryOperator.applyAsDouble(1.1, 2.3)); // 3.4

【4】DoubleUnaryOperator

在这里插入图片描述

(1)applyAsDouble(double operand)

DoubleUnaryOperator doubleUnaryOperator = doub -> doub + 2.5;
System.out.println(doubleUnaryOperator.applyAsDouble(2.6)); // 5.1

(2)andThen(DoubleUnaryOperator after)

DoubleUnaryOperator doubleUnaryOperator = doub -> doub + 2.5;
DoubleUnaryOperator doubleUnaryOperator1 = doub -> doub * 3;
double result = doubleUnaryOperator.andThen(doubleUnaryOperator1)
	.applyAsDouble(10); 
System.out.println(result); // (10 + 2.5) * 3 = 37.5

(3)compose(DoubleUnaryOperator before)

DoubleUnaryOperator doubleUnaryOperator = doub -> doub + 2.5;
DoubleUnaryOperator doubleUnaryOperator1 = doub -> doub * 3;
double result = doubleUnaryOperator.compose(doubleUnaryOperator1)
	.applyAsDouble(10);
System.out.println(result); // 10 * 3 + 2.5 = 32.5

【七】典型实战案例

【1】通用数据校验框架

public static <T, R> void validateField(T target, Function<T, R> getter, 
                                      Predicate<R> validator, String errorMsg) {
    R value = getter.apply(target);
    if (!validator.test(value)) {
        throw new ValidationException(errorMsg);
    }
}

// 调用示例
validateField(user, User::getEmail, 
             email -> email.matches("\\w+@\\w+\\.com"), "邮箱格式错误");

【2】支付网关路由系统

Map<String, Function<PaymentRequest, PaymentResult>> paymentHandlers = new ConcurrentHashMap<>();

// 注册支付方式
paymentHandlers.put("ALIPAY", req -> alipayService.pay(req));
paymentHandlers.put("WECHAT", req -> wechatPayService.transfer(req));

// 路由执行
public PaymentResult processPayment(String channel, PaymentRequest req) {
    return paymentHandlers.get(channel.toUpperCase()).apply(req);
}

【3】对象转换工具​

public static <S, T> T convert(S source, Function<S, T> converter) {
    return Optional.ofNullable(source)
                   .map(converter)
                   .orElseThrow(() -> new IllegalArgumentException("源对象不能为空"));
}

// DTO -> Entity转换
UserEntity entity = convert(userDTO, dto -> 
    new UserEntity(dto.getName(), dto.getEmail()));

【4】异常处理增强

Function<Integer, String> safeParse = num -> {
    try {
        return Integer.toHexString(num);
    } catch (NumberFormatException e) {
        return "INVALID";
    }
};

【5】函数组合工厂

public static Function<String, String> createPipeline(Function<String, String>... functions) {
    return Arrays.stream(functions)
                .reduce(Function.identity(), Function::andThen);
}

// 构建清洗管道
Function<String, String> pipeline = createPipeline(
    String::trim,
    s -> s.replaceAll("\\s+", "_"),
    String::toLowerCase
);

【6】缓存优化​

public class CachedFunction<T, R> implements Function<T, R> {
    private final Function<T, R> delegate;
    private final Map<T, R> cache = new ConcurrentHashMap<>();

    public CachedFunction(Function<T, R> delegate) {
        this.delegate = delegate;
    }

    @Override
    public R apply(T t) {
        return cache.computeIfAbsent(t, delegate);
    }
}

// 使用带缓存的函数
Function<String, BigDecimal> priceCalculator = new CachedFunction<>(this::calculateComplexPrice);
本文章已经生成可运行项目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值