常用的函数式接口
Posted huxiaobai
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了常用的函数式接口相关的知识,希望对你有一定的参考价值。
常用函数式接口
- 仅含有一个抽象方法的接口(不是只有一个方法)
- 该接口常与Lambda表达式相联系
- Lambda表达式延迟加载,可避免性能浪费
Supplier -生产型接口
java.util.function.Supplier<泛型T> 接口仅包含一个无参的方法:T get(),用来获取一个泛型参数指定类型的对象数据。由于这是一个函数式接口,也就意味着对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象数据。
Supplier<>接口被称为生产型接口,指定接口的泛型是什么类型,那么接口的get方法就会生产什么类型的数据,有返回值。
package cn.learn;
import java.util.function.Supplier;
public class function
//定义一个方法,方法参数传递Supplier<>接口,泛型执行String.get方法就会返回一个String
public static String getString(Supplier<String> stringSupplier)
return stringSupplier.get();
public static void main(String[] args)
//调用getString方法,方法的参数是一个函数式表达接口,所以传递lambda表达式
String str = getString(() ->
//生产一个字符串,并返回
return "aaa";
);
System.out.println(str);
//优化Lambda表达式
str = getString(() -> "aaa");
System.out.println(str);
练习:求数组元素最大值
package cn.learn;
import java.util.function.Supplier;
public class function
public static Integer getMax(Supplier<Integer> stringSupplier)
return stringSupplier.get();
public static void main(String[] args)
//定义一个数组
int[] arr = new int[]3,55,66,77,88,-5;
//调用getMax方法,使用Lambda表达式简写
int integermax = getMax(() ->
//获取数组最大值并返回
int max = arr[0];
for (int i = 1; i < arr.length; i++)
if (max < arr[i])
max = arr[i];
return max;
);
/******
//调用getMax方法
getMax(new Supplier<Integer>()
@Override
public Integer get()
//获取数组最大值并返回
int max = arr[0];
for (int i = 1; i < arr.length; i++)
if (max < arr[i])
max = arr[i];
return max;
);
*******/
System.out.println(integermax);
Consumer -消费型接口
java.util.function.Consumer<泛型>接口正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据,其数据类型由泛型决定
Consumer接口中包含抽象方法void accept(T t),意为消费一个指定泛型的数据,无返回值
package cn.learn;
import java.util.function.Consumer;
public class function
//accept方法接受的数据可以输出、计算等
public static void print(Integer year,Consumer<Integer> age)
age.accept(year);
public static void main(String[] args)
//消费方式:直接输出
print(2018,(year) -> System.out.println("你的出生年是"+year));
//消费方式:反转字符串
print(2018,(year) ->
String string = year.toString();
String re = new StringBuilder(string).reverse().toString();
System.out.println(re);
);
Consumer方法中的默认方法——andThen
如果一个方法的参数和返回值全部是Consumer类型,那么就可以实现:消费数据的时候,首先做一个操作,然后在做一个操作,实现组合,而这个方法就是Consumer接口中的default方法
JDK源码
default Consumer<T> andThen(Consumer<? super T> after)
Objects.requireNonNull(after);
return (T t) -> accept(t); after.accept(t); ;
注:java.util.Object的requireNonNull静态方法将会在参数为null时主动抛出NullPointerException异常,这就省去编写if语句和抛出空指针异常的麻烦。
若想实现组合效果,需要两个Lambda表达式即可,而andThen的语义正是“一步接一步”操作,例如两个步骤组合的情况:
- Consumer<泛型String> con1;
Consumer<泛型String> con2;
String str = "hello";
con1.accept(str);
con2.accept(str);
- Consumer<泛型String> con1;
package cn.learn;
import java.util.function.Consumer;
public class function
//把两个Consumer接口组合到一起,再对数据进行消费
public static void method(String str,Consumer<String> con1,Consumer<String> con2)
//使用原始方式
con1.accept(str);
con2.accept(str);
public static void main(String[] args)
//原始使用方式,调用method方法,需要传递两个Lambda表达式
method("Hello",(str) ->
//消费方式:转为大写
System.out.println(str.toUpperCase());
,(str) ->
//消费方式:转为小写
System.out.println(str.toLowerCase());
);
- 连接两个接口再进行消费(谁在前,谁先消费),可以改为
con1.andThen(con2).accept(str);
package cn.learn;
import java.util.function.Consumer;
public class function
//andThen需要两个Consumer接口,可以把两个Consumer接口组合到一起,再对数据进行消费
public static void method(String str,Consumer<String> con1,Consumer<String> con2)
//先使用con1消费数据,再使用con2
con1.andThen(con2).accept(str);
public static void main(String[] args)
//原始使用方式,调用method方法,需要传递两个Lambda表达式
method("Hello",(str) ->
//消费方式:转为大写
System.out.println(str.toUpperCase());
,(str) ->
//消费方式:转为小写
System.out.println(str.toLowerCase());
);
练习:格式化打印信息
package cn.learn;
import java.util.function.Consumer;
public class function
//使用两个Consumer来消费字符串,泛型为字符数组
public static void method(String[] str,Consumer<String[]> con1,Consumer<String[]> con2)
//先使用con1消费数据,再使用con2
con1.andThen(con2).accept(str);
public static void main(String[] args)
//定义一个字符串数组
String[] person ="小王,男","大王,女";
//原始使用方式,调用method方法,需要传递两个Lambda表达式
method(person,(str) ->
//消费方式:取人名
for (String name:str)
//取第一个元素
System.out.println(name.split(",")[0]);
,(str) ->
//消费方式:取性别
for (String name:str)
//取第一个元素
System.out.println(name.split(",")[1]);
);
结果:
小王
大王
男
女
- 另一种写法
package cn.learn;
import java.util.function.Consumer;
public class function
//使用两个Consumer来消费字符串,泛型为字符数组
public static void method(String[] str,Consumer<String> con1,Consumer<String> con2)
//将遍历写在此处,预防重复造轮子
for (String message:str)
//先使用con1消费数据,再使用con2
con1.andThen(con2).accept(message);
public static void main(String[] args)
//定义一个字符串数组
String[] person ="小王,男","大王,女";
//原始使用方式,调用method方法,需要传递两个Lambda表达式
method(person,(message) ->
//消费方式:取人名
System.out.println(message.split(",")[0]);
,(message) ->
//消费方式:取性别
System.out.println(message.split(",")[1]);
);
结果:
小王
男
大王
女
Predicate -判断接口
有时候我们需要对某种数据类型的数据进行判断,从而得到一个boolean值的结果,这时可以使用java.util.function.predicate<泛型>接口
Predicate接口中含有一个抽象方法:boolean test(T t)。用于条件判断的场景,返回值为布尔值
```java
package cn.learn;
import java.util.function.Predicate;
public class function
//
public static boolean checkMethod(String str, Predicate
return pre.test(str);
public static void main(String[] args)
String str = "hello";
//对字符串进行校验
boolean check = checkMethod(str,(String str01) ->
return str01.length()>5;
);
boolean check1 = checkMethod(str,str01 -> str01.length()>3);
System.out.println(check);
System.out.println(check1);
- 默认方法:and -可以判断多个判断条件和“&&”差不多
package cn.learn;
import java.util.function.Predicate;
public class function
//
public static boolean checkMethod(String str, Predicate<String> pre1, Predicate<String> pre2)
//等价于return pre1.test(str) && pre2.test(str);
return pre1.and(pre2).test(str);
public static void main(String[] args)
String str = "hello";
//对字符串进行校验
boolean check = checkMethod(str,(String str01) ->
return str01.length()>3;
,(str01) ->
return str01.contains("1");
);
System.out.println(check);
false
- 默认方法:or -可以判断多个判断条件和“||”差不多
package cn.learn;
import java.util.function.Predicate;
public class function
//
public static boolean checkMethod(String str, Predicate<String> pre1, Predicate<String> pre2)
//等价于return pre1.test(str) || pre2.test(str);
return pre1.or(pre2).test(str);
public static void main(String[] args)
String str = "hello";
//对字符串进行校验
boolean check = checkMethod(str,(String str01) ->
return str01.length()>3;
,(str01) ->
return str01.contains("1");
);
System.out.println(check);
true
- 默认方法:negate -可以判断多个判断条件和“!”差不多
package cn.learn;
import java.util.function.Predicate;
public class function
//
public static boolean checkMethod(String str, Predicate<String> pre1)
//等价于return !pre1.test(str);
return pre1.negate().test(str);
public static void main(String[] args)
String str = "hello";
//对字符串进行校验
boolean check = checkMethod(str,(String str01) ->
return str01.length()>3;
);
System.out.println(check);
false
练习:集合信息筛选
- 将名字为2个字且为女生的字符串选到集合中,注意字符串判断需要用equals方法
package cn.learn;
import java.util.ArrayList;
import java.util.function.Predicate;
public class function
public static ArrayList<String> filter(String[] str, Predicate<String> pre1, Predicate<String> pre2)
//放外边,里边会重复申请
ArrayList<String> correct = new ArrayList<>();
//遍历数组
for (String message : str)
boolean ifCorr = pre1.and(pre2).test(message);
//满足条件的放入集合
if (ifCorr)
correct.add(message);
return correct;
public static void main(String[] args)
String[] str = "小王,女", "大王,男", "小白,男", "王小白,女";
//对字符串进行筛选,并返回需要的集合
ArrayList<String> list = filter(str, (String str01) ->
return str01.split(",")[0].length() == 2;
, (str01) -> str01.split(",")[1].equals("女") );
System.out.println(list);
[小王,女]
Function -数据类型转换接口
java.util.function.Function<T,R>接口用来根据一个数据类型得到另一个数据类型,前者称为前置条件,后者称为后置条件。
抽象方法:apply,R apply
,根据类型T的参数获取R型的结果,返回的是另一个类型的值。
package cn.learn;
import java.util.function.Function;
public class function
public static Integer convert(String str, Function<String,Integer> function)
//返回一个Integer类型
return function.apply(str);
public static void main(String[] args)
String str = "2018";
//调用convert方法转换类型,并用Lambda表达式重写apply方法
Integer strInt = convert(str,(String str01) ->
return Integer.parseInt(str01);
);
System.out.println(strInt);
默认方法:andThen,用来进行组合操作
需求:把字符串转换为Integer类型,把结果进行运算,
再把整型转换回去
package cn.learn;
import java.util.function.Function;
public class function
public static String convert(String str, Function<String,Integer> fun1,Function<Integer,String> fun2)
//返回一个String类型
return fun1.andThen(fun2).apply(str);
public static void main(String[] args)
String str = "2018";
//调用convert方法转换类型,取出字符串对应的值并进行运算,再转换为String
str = convert(str,str01 ->Integer.parseInt(str01)+10,int01 -> int01.toString());
System.out.println(str);
2028
以上是关于常用的函数式接口的主要内容,如果未能解决你的问题,请参考以下文章