java8学习(三)函数式接口
1. 函数式接口 的产生
在学习完Lambda表达式之后得到结论:使用Lambda表达式的前提是需要有函数式接口,而Lambda表达式使用时不关心接口名,抽象方法名。只关心抽象方法的参数列表和返回值类型。因此为了让我们使用Lambda表达式更加的方便,在JDK中提供了大量常用的函数式接口。
2.函数式接口介绍及使用
在JDK中帮我们提供的有函数式接口,主要是在 java.util.function 包中。
2.1 Supplier
无参有返回值的接口,对于的Lambda表达式需要提供一个返回数据的类型。
接口:
@FunctionalInterface
public interface Supplier<T> {
/**
* Gets a result.
*
* @return a result
*/
T get();
}
使用案例:
public class SupplierFunction {
public static void main(String[] args) {
funcSupplier(()->{
//创建一个数组
Integer arrs [] = {1, 2, 3, 6, 10, 50, 30, 22, 9};
//对数组进行自然顺序排序
Arrays.sort(arrs);
//数组得最后一个下标对应得数据即为最大值
return arrs[arrs.length-1];
});
}
/**
* 获取最大值
* @param supplier
*/
private static void funcSupplier(Supplier<Integer> supplier){
Integer max = supplier.get();
System.out.println("最大值为:"+max);
}
}
控制台输出:
最大值为:50
2.2 Consumer
有参无返回值得接口,前面介绍的Supplier接口是用来生产数据的,而Consumer接口是用来消费数据的,使用的时候需要指定一个泛型来定义参数类型
接口:
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
使用accept()
public class ConsumerFunction {
public static void main(String[] args) {
funConsumer(s -> {
System.out.println("得到参数"+s+"转换为小写====>"+s.toLowerCase());
});
}
private static void funConsumer(Consumer<String> consumer){
consumer.accept("Hello World");
}
}
控制台输出:
得到参数Hello World转换为小写====>hello world
默认andThen 方法:
如果一个方法的参数和返回值全部是Consumer类型,那么就可以实现效果,消费一个数据的时候,首先做一个操作,然后再做一个操作,实现组合,而这个方法就是Consumer接口中的default方法andThen方法。
使用案例:
public class ConsumerFunction {
public static void main(String[] args) {
funConsumerAndThen(s1->{
System.out.println("得到参数"+s1+"转换为小写====>"+s1.toLowerCase());
},s2->{
System.out.println("得到参数"+s2+"转换为大写====>"+s2.toUpperCase());
});
}
private static void funConsumerAndThen(Consumer<String> c1,Consumer<String> c2){
c1.andThen(c2).accept("Hello World");
}
}
控制台输出:
得到参数Hello World转换为小写====>hello world
得到参数Hello World转换为大写====>HELLO WORLD
2.3 Function
有参有返回值的接口,Function接口是根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。有参数有返回值。
接口:
@FunctionalInterface
public interface Function<T, R> {
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));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
使用R apply(T t);
public static void main(String[] args) {
testFunction(s-> String.valueOf(s));
}
/**
* 将数字转为String
* @param f
*/
private static void testFunction(Function<Integer,String> f){
String apply = f.apply(123);
System.out.println("apply:"+apply);
}
控制台输出:
apply:123
使用andThen(Function<? super R, ? extends V> after)方法
将结果应用与after上,是一个组合操作
public static void main(String[] args) {
testFunction2(s-> Integer.parseInt(s),s2-> String.valueOf(s2+1));
}
private static void testFunction2(Function<String,Integer> f,Function<Integer,String> f2){
String apply = f.andThen(f2).apply("99");
System.out.println(apply);
}
控制台输出:
100
使用compose(Function<? super V, ? extends T> before)
先执行before,然后用于其他操作,与andThen相反
public static void main(String[] args) {
testFunction3(s->Integer.parseInt(s), s2->String.valueOf(s2+1));
}
private static void testFunction3(Function<String,Integer> f,Function<Integer,String> f2){
Integer apply = f.compose(f2).apply(99);
System.out.println("testFunction3==>apply:"+apply);
}
控制台输出:
testFunction3==>apply:100
静态方法identity则是,输入什么参数就返回什么参数。
2.4 Predicate
有参数且返回值为boolean的接口
接口:
@FunctionalInterface
public interface Predicate<T> {
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);
}
}
使用test:
public static void main(String[] args) {
funPredicate(msg -> ms
g.length() > 3 ,"mx");
}
private static void funPredicate(Predicate<String> predicate,String msg){
boolean b = predicate.test(msg);
System.out.println("传入的参数长度大于三是否成立" + b);
}
使用 and or negate 方法
public static void main(String[] args) {
funPredicateTest(
p1m->p1m.length()>2,
p2m->p2m.startsWith("H"),
"Hello"
);
}
private static void funPredicateTest(Predicate<String> p1,Predicate<String> p2,String msg){
boolean b = p1.and(p2).test(msg);
System.out.println(msg+":长度大于2并且首字母是是否成立:" + b);
boolean b2 = p1.or(p2).test(msg);
System.out.println(msg+":长度大于2或者首字母是是否成立:" + b2);
//取反
boolean b3 = p2.negate().test(msg);
System.out.println(msg+":首字母不包括H,是否成立:" + b3);
}
控制台输出:
Hello:长度大于2并且首字母是是否成立:true
Hello:长度大于2或者首字母是是否成立:true
Hello:首字母不包括H,是否成立:false
使用isEqual方法
public static void main(String[] args) {
String s="Hello";
System.out.println(Predicate.isEqual(s).test("Hello"));
}
控制台输出
true