JDK8新特性–函数式接口
前言—回顾lambda表达式
要说明白什么是函数式接口,就要回到我们之前学习到的lambda表达式了,我们都知道,我们要使用lambda表达式的话,需要一个接口,而且该接口内只能有一个抽象方法,比如说下面这个例子:
package com.features.functionInterface;
public class originalMethod {
public static void main(String[] args) {
Sum(a->{
int sum = 0;
for (int i : a) {
sum+=i;
}
return sum;
});
}
public static void Sum(Test test){
int[] a ={1,2,3,4,5,6,7,8,9};
int sum = test.getSum(a);
System.out.println("sum="+sum);
}
}
// 函数式接口
@FunctionalInterface
interface Test{
int getSum(int[] arr);
}
复制代码
这时候,我们就会发现一个问题:我们每次需要使用lambda表达式的时候,都需要函数式接口和抽象方法,就很麻烦。而lambda表达式在使用时不关心接口名,抽象方法名,只关心抽象方法的参数列表和返回值类型。
因此,JDK8为了让我们使用lambda表达式更加的方便,在JDK中提供了大量的函数式接口。
函数式接口详解
函数式接口的种类
位置在lib包下lib\rt.jar!\java\util\function
,在这里可以看到JDK提供给我们的函数式接口
在这里我就挑选几个比较常用的函数式接口来进行讲解,其他如果还有兴趣的,可以自己去翻阅源码。
Supplier
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
复制代码
- 无参有返回值 用来生产数据
- 案例实现:找出数组中的最大值
package com.features.functionInterface;
import java.util.Arrays;
import java.util.function.Supplier;
// 使用JDK8定义的函数式接口Supplier
// Supplier:无参有返回值 用来生产数据
public class SupplierTest {
public static void main(String[] args) {
getMax(()->{
int[] a={1,2,5,3,6,4,8,9,7};
Arrays.sort(a);
return a[a.length-1];
});
}
public static void getMax(Supplier<Integer> supplier){
Integer max = supplier.get();
System.out.println("Max:"+max);
}
}
复制代码
结果:
Consumer
@FunctionalInterface
public interface Consumer<T> {
/**
* Performs this operation on the given argument.
*
* @param t the input argument
*/
void accept(T t);
/**
* Returns a composed {@code Consumer} that performs, in sequence, this
* operation followed by the {@code after} operation. If performing either
* operation throws an exception, it is relayed to the caller of the
* composed operation. If performing this operation throws an exception,
* the {@code after} operation will not be performed.
*
* @param after the operation to perform after this operation
* @return a composed {@code Consumer} that performs in sequence this
* operation followed by the {@code after} operation
* @throws NullPointerException if {@code after} is null
*/
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
复制代码
- 有参无返回值 用来消费数据
andThen
默认方法 用来组合方法实现- 案例实现:字符串大小写转换
package com.features.functionInterface;
import java.util.function.Consumer;
// Consumer: 有参无返回值 用来消费数据
public class ConsumerTest {
public static void main(String[] args) {
change(message -> System.out.println(message + "转换为小写后,变成" + message.toLowerCase()));
changeAndThen(msg1 -> System.out.println(msg1 + "转换为小写后,变成" + msg1.toLowerCase()),
msg2 -> System.out.println(msg2 + "转换为大写后,变成" + msg2.toUpperCase()));
}
public static void change(Consumer<String> consumer) {
consumer.accept("Hello,Consumer");//转换为小写
}
public static void changeAndThen(Consumer<String> c1, Consumer<String> c2) {
String str = "Hello,World";
// 第一种写法,分别调用
//c1.accept(str); // 转换为小写
//c2.accept(str); // 转换为大写
// 第二种用法 先执行c1,再执行c2
//c1.andThen(c2).accept(str);
// 第二种用法 先执行c2,再执行c1
c2.andThen(c1).accept(str);
}
}
复制代码
结果:
Function
- 有参有返回值:根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。
andThen
默认方法,组合实现compose
默认方法,组合实现,和andThen
效果相反Function
静态方法,返回自身传递的参数
@FunctionalInterface
public interface Function<T, R> {
/**
* Applies this function to the given argument.
*
* @param t the function argument
* @return the function result
*/
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));
}
/**
* Returns a function that always returns its input argument.
*
* @param <T> the type of the input and output objects to the function
* @return a function that always returns its input argument
*/
static <T> Function<T, T> identity() {
return t -> t;
}
复制代码
- 案例实现:字符串和数字的转换
package com.features.functionInterface;
import java.util.function.Function;
// Function: 有参有返回值 根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。
public class FunctionTest {
public static void main(String[] args) {
//test1(msg-> Integer.parseInt(msg));
// 也可以替换为
test1(Integer::parseInt);
// andThen
test2(msg1-> {
int i = Integer.parseInt(msg1);
System.out.println("字符串转为数字,结果为:"+i);
return i;
}, msg2->{
String s = String.valueOf(msg2);
System.out.println("数字转为字符串,结果为:"+s);
return s;
});
test3(msg1-> {
int i = Integer.parseInt(msg1);
System.out.println("字符串转为数字,结果为:"+i);
return i;
}, msg2->{
String s = String.valueOf(msg2);
System.out.println("数字转为字符串,结果为:"+s);
return s;
});
}
public static void test1(Function<String,Integer> function){
String str = "123";
Integer apply = function.apply(str);//字符串转换为数字
System.out.println("字符串转为数字,结果为:"+apply);
}
public static void test2(Function<String,Integer> f1,Function<Integer,String> f2){
String str = "456";
//Integer i = f1.apply(str);//字符串转为数字
//f2.apply(i);// 数字转为字符串
f1.andThen(f2).apply(str);
}
public static void test3(Function<String,Integer> f1,Function<Integer,String> f2){
Integer i = 789;
//String s = f1.apply(str);//数字转为字符串
//f2.apply(s);// 字符串转为数字
f1.compose(f2).apply(i);
}
}
复制代码
Predicate
- 有参有返回值,返回值为boolean类型
and
默认方法 a&&b a,b全对才对or
默认方法 a||b a,b有一个对就对negate
默认方法 !a a对就错,a错就对isEqual
静态方法
@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);
}
/**
* Returns a predicate that represents the logical negation of this
* predicate.
*
* @return a predicate that represents the logical negation of this
* predicate
*/
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);
}
/**
* Returns a predicate that tests if two arguments are equal according
* to {@link Objects#equals(Object, Object)}.
*
* @param <T> the type of arguments to the predicate
* @param targetRef the object reference with which to compare for equality,
* which may be {@code null}
* @return a predicate that tests if two arguments are equal according
* to {@link Objects#equals(Object, Object)}
*/
static <T> Predicate<T> isEqual(Object targetRef) {
return (null == targetRef)
? Objects::isNull
: object -> targetRef.equals(object);
}
复制代码
- 案例实现:字符串的操作
package com.features.functionInterface;
import java.util.function.Predicate;
// Predicate : 有参有返回值,返回值为boolean类型
public class PredicateTest {
public static void main(String[] args) {
test(msg -> msg.length() > 3, "hello");
test2(msg1 -> msg1.contains("h"), msg2 -> msg2.contains("r"));
}
public static void test(Predicate<String> predicate, String str) {
boolean test = predicate.test(str);
System.out.println("字符串的长度大于3?" + test);
}
public static void test2(Predicate<String> p1, Predicate<String> p2) {
//boolean b1 = p1.test("h"); // b1中是否有h
//boolean b2 = p2.test("r");// b2中是否有r
boolean flag1 = p1.and(p2).test("hello");// p1 && p2
boolean flag2 = p1.or(p2).test("hello"); // p1 || p2
boolean flag3 = p1.negate().test("hello"); // !p1
System.out.println("hello中是否同时存在h和r:"+flag1);
System.out.println("hello中是否有h和r的任意一个:"+flag2);
System.out.println("hello中不包含h:"+flag3);
}
}
复制代码
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END