Java8函数式接口编程lambda表达式FunctionalInterface注解SupplierConsumerPredicateFunction函数式接口
Posted Roninaxious
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java8函数式接口编程lambda表达式FunctionalInterface注解SupplierConsumerPredicateFunction函数式接口相关的知识,希望对你有一定的参考价值。
1、函数式接口的定义
有且仅有一个抽象方法的接口
函数式接口顾名思义就是函数式编程的接口,在Java中最能体现函数式编程的无非就是Lambda,所以函数式接口是可以适用于Lambda使用的接口;
只有确保只有一个抽象方法,Lambda才能顺利地推导
2、FunctionalInterface注解
该注解与Override注解类似,FunctionalInterface用来检测该接口是否是一个函数式接口(只有一个抽象方法)
被@FunctionalInterface注解标记的类型表明这是一个函数接口。从概念上讲,函数接口只有一个抽象方法。如果接口声明的抽象方法覆写Object类的公共方法,那这方法不算作接口的抽象方法,因为接口具有Object方法的默认实现。
3、函数式接口的使用
首先定义一个函数式接口
@FunctionalInterface
public interface MyFunctionInterface {
public abstract void method();
}
(1)第一种使用方式(实现接口)
重写接口
在testFun方法参数中定义接口
调用时传入它的实现类
public class MyFunctionInterfaceImpl implements MyFunctionInterface{
@Override
public void method() {
System.out.println("第一种函数式接口的使用方式...");
}
}
public class TestFunctionInterface {
public static void testFun(MyFunctionInterface myFunctionInterface) {
myFunctionInterface.method();
}
public static void main(String[] args) {
testFun(new MyFunctionInterfaceImpl());
}
}
(2)内名内部类
testFun(new MyFunctionInterface() {
@Override
public void method() {
System.out.println("第二种实现方式...");
}
});
(3)Lambda表达式
testFun(()->{
System.out.println("第三种实现方式");
});
或者
testFun(()-> System.out.println("第三种实现方式"));
4、lambda延迟执行特性
使用一个日志案例来演示
public class lambdaLater {
public static void log(int k, String msg) {
if (k == 1) {
System.out.println(msg);
}
}
public static void main(String[] args) {
String msg1 = "aa";
String msg2 = "bb";
String msg3 = "cc";
log(2, msg1 + msg2 + msg3);
}
}
根据上文代码,如果传入的k=2,那么日志不会打印,但是msg1 + msg2 + msg3已经完成了拼接,这样就会浪费性能。
❤️ 经过lambda优化
使用lambda之前,首先需要定义一个函数式接口。
@FunctionalInterface
public interface LambdaLaterInterface {
public abstract String printMsg();
}
测试
public class lambdaLater {
public static void log2(int k, LambdaLaterInterface lambdaLaterInterface) {
if (k == 1) {
System.out.println(lambdaLaterInterface.printMsg());
}
}
public static void main(String[] args) {
String msg1 = "aa";
String msg2 = "bb";
String msg3 = "cc";
log2(2, () -> {
System.out.println("------");
return msg1 + msg2 + msg3;
});
}
}
结果如下
没有“-------”,说明字符串没有进行拼接。
5、Supplier函数式接口
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
根据Supplier源代码可以看出,Supplier接口中是一个无参的的抽象方法;当你接口泛型指定什么类型,那么T get()抽象方法就会返回什么类型。
所以Supplier被成为生产型接口
public class SupplierDemo {
public static String sup(Supplier<String> supplier) {
return supplier.get();
}
public static void main(String[] args) {
//只有一行代码,省略了return和{}和,
String s = sup(() -> "hello");
System.out.println(s);
}
}
public class SupplierDemo {
public static int getMax(Supplier<Integer> sup) {
return sup.get();
}
public static void main(String[] args) {
int[] nums = {1, 3, 5, 0, 9};
int maxNum = getMax(() -> {
int max = nums[0];
for (int temp : nums) {
if (temp > max)
max = temp;
}
return max;
});
System.out.println(maxNum);
}
}
6、Consumer函数式接口
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
这个Consumer接口刚好和Supplier接口的作用相反,如果接口泛型定义了什么类型,那么方法accept就可以消费什么类型;
Consumer是一个典型的消费型接口
public class ConsumerDemo {
public static void strRev(String str, Consumer<String> con) {
con.accept(str);
}
public static void main(String[] args) {
strRev("test", (temp) -> {
String result = new StringBuilder(temp).reverse().toString(); //反转字符串
System.out.println(result);
});
}
}
在Consumer接口中,有一个默认的方法andThen
这个andThen方法的作用是对两个Consumer接口进行连接消费
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
public class ConsumerDemo {
public static void strRev(String str, Consumer<String> consumer, Consumer<String> consumer2) {
consumer.andThen(consumer2).accept(str);
}
//进行组合消费
strRev("hello",
(name) -> {
System.out.println(name.toLowerCase());
},
(name2) -> {
System.out.println(name2.toUpperCase());
});
}
}
7、Predicate函数式接口
源代码中包含了一个抽象方法test和四个默认方法
@FunctionalInterface
public interface Predicate<T> {
/**
* Evaluates this predicate on the given argument.
*
* @param t the input argument
* @return {@code true} if the input argument matches the predicate,
* otherwise {@code false}
*/
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 class PredicateDemo {
public static boolean predicate(int a, Predicate<Integer> predicate) {
return predicate.test(a);
}
public static void main(String[] args) {
boolean flag = predicate(6, (num) -> {
return num > 5;
});
System.out.println(flag);
}
}
and方法的用法,与&&等同
public class PredicateDemo {
public static boolean predicate2(int a, Predicate<Integer> pre, Predicate<Integer> pre2) {
return pre.and(pre2).test(a);
}
public static void main(String[] args) {
boolean flag2 = predicate2(6,
(num) -> {
return num > 2;
},
(num2) -> {
return num2 > 8;
});
System.out.println(flag2);
}
}
or方法和and方法类似,与||等同。
negate方法,与!(取反)等同。
8、Function函数式接口
andThen方法的应用
在fun的基础上,fun2在进行加20,结果等于42;
public static Integer function2(String s, Function<String, Integer> fun, Function<Integer,Integer> fun2) {
return fun.andThen(fun2).apply(s);
}
public static void main(String[] args) {
Integer a = function2("12", (num) -> {
return Integer.valueOf(num) + 10;
}, (num)->{
return num + 20;
});
System.out.println(a);
}
以上是关于Java8函数式接口编程lambda表达式FunctionalInterface注解SupplierConsumerPredicateFunction函数式接口的主要内容,如果未能解决你的问题,请参考以下文章