函数式接口(Function,Predicate,Supplier,Consumer)
Function
- 常用的方法 R apply(T t)
将Function对象应用到输入的参数上,然后返回计算结果。
测试例子
public class TestFunction {
/**
* Function<T t,R r>函数式接口
* R apply(T t); 数据类型转换
*
* @param s
* @param function
*/
public static void change(String s, Function<String, Integer> function) {
//字符串类型的整数 转换为Integer类型的整数
int in = function.apply(s);
System.out.println(in);
}
/**
* andThen(Function<T t,R r>);
*
* @param s
* @param fun1
* @param fun2
*/
public static void change02(String s, Function<String, Integer> fun1, Function<Integer, String> fun2) {
String ss = fun1.andThen(fun2).apply(s);
System.out.println(ss);
}
public static int change03(String s, Function<String, String> fun1, Function<String, Integer> fun2, Function<Integer, Integer> fun3) {
return fun1.andThen(fun2).andThen(fun3).apply(s);
}
public static void main(String[] args) {
String s = "12345";
String ss = "小小明,20";
change(s, str -> Integer.parseInt(s));
change02(s, str -> Integer.parseInt(s) + 10, i -> i + "");
int num = change03(ss, str -> str.split(",")[1], str -> Integer.parseInt(str), i -> i + 100);
System.out.println("num: " + num);
}
}
结果
12345
12355
num: 120
Predicate
有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。这时可以使用java.util.function.Predicate 接口。
-
常用的方法
boolean test(T t);
Predicate 接口中包含一个抽象方法,返回一个boolean值进行判断。
测试例子
public class TestPredicate {
/**
* boolean test(T t); 获取布尔类型结果
*
* @param s
* @param pre
* @return
*/
public static boolean checkString(String s, Predicate<String> pre) {
return pre.test(s);
}
/**
* and(); 代表&&的意思
* <p>
* 传递两个Predicate接口,比如:
* 一个用于判断字符串的长度是否大于5
* 一个用于判断字符串中是否包含a
* 两个条件必须同时满足
*
* @param s
* @param pre
* @return
*/
public static boolean checkStringAnd(String s, Predicate<String> pre1, Predicate<String> pre2) {
return pre1.and(pre2).test(s);
}
/**
* or(); 代表||的意思
*
* @param s
* @param pre1
* @param pre2
* @return
*/
public static boolean checkStringOr(String s, Predicate<String> pre1, Predicate<String> pre2) {
return pre1.or(pre2).test(s);
}
/**
* negate取反
*
* @param s
* @param pre
* @return
*/
public static boolean checkStringNegate(String s, Predicate<String> pre) {
return pre.negate().test(s);
}
/**
* 方法的参数传递一个包含人员信息的数组
* 传递两个Predicate接口,用于对数组中信息进行过滤
* 把满足条件的信息存到ArrayList集合中并返回
*
* @return
*/
public static ArrayList<String> filter(String arr[], Predicate<String> pre1, Predicate<String> pre2) {
ArrayList<String> list = new ArrayList<>();
for (String s : arr) {
boolean b = pre1.and(pre2).test(s);
if (b) {
list.add(s);
}
}
return list;
}
public static void main(String[] args) {
String s = "abcdef";
//长度大于5
boolean b = checkString(s, str -> str.length() > 5);
System.out.println(b);
//长度大于6并且包含"a"
boolean and = checkStringAnd(s, str -> str.length() > 6, str -> str.contains("a"));
System.out.println(and);
//长度大于6 或者 包含"a"
boolean or = checkStringOr(s, str -> str.length() > 6, str -> str.contains("a"));
System.out.println(or);
//取反
boolean negate = checkStringNegate(s, str -> str.length() > 5);
System.out.println(negate);
//过滤操作
String arr[] = {"张小三,男", "小红,女", "李四,男", "小小明,男"};
ArrayList<String> list = filter(arr, str -> "男".equals(str.split(",")[1])
, str -> str.split(",")[0].length() > 2);
list.forEach(System.out::println);
}
}
结果
true
false
true
false
张小三,男
小小明,男
Supplier
泛型传递什么类型数据,get方法就返回什么类型数据。所以Supplier被称之为生产型接口
-
常用的方法
T get();
该接口中只包含这一个抽象方法。
测试例子
public class TestSupplier {
public static void main(String[] args) {
String s = getString(() -> {
return "hello world";
});
System.out.println(s);
//优化lambda
String s2 = getString(() -> "hello java");
System.out.println(s2);
int[] arr = {34, 45, 23, 1, 345, -54};
int maxVal = getMax(() -> {
int max = arr[0];
for (int i : arr) {
if (i > max) {
max = i;
}
}
return max;
});
System.out.println(maxVal);
}
/**
* 会返回一个String
*
* @param sup
* @return
*/
public static String getString(Supplier<String> sup) {
return sup.get();
}
/**
* 返回一个最大值
*
* @param sup
* @return
*/
public static int getMax(Supplier<Integer> sup) {
return sup.get();
}
}
结果
hello world
hello java
345
Consumer
java.util.function.Consumer 接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据, 其数据类型由泛型决定。
-
常用的方法
void accept(T t);
Consumer 接口中包含抽象方法 void accept(T t) ,意为消费一个指定泛型的数据。
测试例子
public class TestConsumer {
public static void method(String name, Consumer<String> consumer) {
consumer.accept(name);
}
public static void method02(String name, Consumer<String> con1, Consumer<String> con2) {
//使用andThen方法,先把两个Consumer接口连接在一起,在消费数据
//con1连接con2,先执行con1消费数据,在执行con2消费数据
con1.andThen(con2).accept(name);
}
public static void printInfo(String[] arr, Consumer<String> con1, Consumer<String> con2) {
for (String message : arr) {
con1.andThen(con2).accept(message);
}
}
public static void main(String[] args) {
method("neoooo", (name) -> {
//对传递的字符串进行消费
//消费方式:直接输出字符串
//System.out.println(name);
//消费方式:把字符串进行反转输出
String reverse = new StringBuffer(name).reverse().toString();
System.out.println(reverse);
});
//调用method02方法,传递一个字符串,两个lambda表达式
method02("nizhenniubi", (name) -> {
System.out.println(name.toUpperCase());
}, (name) -> {
System.out.println(name.toLowerCase());
});
String arr[] = {"zhangsan,male", "lisi,male", "wanger,female"};
printInfo(arr, (message) -> {
String name = message.split(",")[0];
System.out.println("姓名:" + name);
}, (message) -> {
String sex = message.split(",")[1];
System.out.println("性别:" + sex + " ");
});
}
}
结果
ooooen
NIZHENNIUBI
nizhenniubi
姓名:zhangsan
性别:male
姓名:lisi
性别:male
姓名:wanger
性别:female
混合使用
例子
public class TestAll {
static List<Emp> emps = Arrays.asList(
new Emp(1, "yw"),
new Emp(2, "yt"),
new Emp(3, "yp"),
new Emp(4, "yc"));
private static <T,R> void printEmpNameWhenEmpNoLg1(Iterable<T> source, Predicate<T> predicate, Function<T,R> function,
Consumer<R> consumer)
{
for(T t:source)
{
if(predicate.test(t))
{
R r = function.apply(t);
consumer.accept(r);
}
}
}
public static void main(String[] args) {
Predicate<Emp> predicate = emp -> emp.getEmpno()>2;
//定义函数
Function<Emp,String> function = emp -> emp.getEname();
//定义消费者
Consumer<String> consumer = System.out::println;
TestAll.printEmpNameWhenEmpNoLg1(emps,predicate,function,consumer);
}
}
public class Emp {
private int empno;
private String ename;
public Emp(int empno, String ename) {
this.empno = empno;
this.ename = ename;
}
public int getEmpno() {
return empno;
}
public void setEmpno(int empno) {
this.empno = empno;
}
public String getEname() {
return ename;
}
public void setEname(String ename) {
this.ename = ename;
}
public static void printEmp(Emp emp){
System.out.println("empno:"+emp.getEmpno()+"\nename:"+emp.getEname());
}
}
结果
yp
yc