1、概述
有且只有一个抽象方法的接口,称之为函数式接口、当然接口中可以包含其他的方法(默认,静态,私有)
使用@FunctionalInterface注解
以下是函数式接口的使用
// MyFunctionalInterface.java
@FunctionalInterface
public interface MyFunctionalInterface {
//定义一个抽象方法
public abstract void method();
}
// MyFunctionalInterfaceImpl.java
public class MyFunctionalInterfaceImpl implements MyFunctionalInterface{
@Override
public void method() {
}
}
// Demo.java
public class Demo {
//定义一个方法,参数使用函数式接口MyFunctionalInterface
public static void show(MyFunctionalInterface myInter){
myInter.method();
}
public static void main(String[] args) {
//调用show方法,方法的参数是一个接口,所以可以传递接口的实现类对象
show(new MyFunctionalInterfaceImpl());
//调用show方法,方法的参数是一个接口,所以我们可以传递接口的匿名内部类
show(new MyFunctionalInterface() {
@Override
public void method() {
System.out.println("使用匿名内部类重写接口中的抽象方法");
}
});
//调用show方法,方法的参数是一个函数式接口,所以我们可以Lambda表达式
show(()->{
System.out.println("使用Lambda表达式重写接口中的抽象方法");
});
//简化Lambda表达式
show(()-> System.out.println("使用Lambda表达式重写接口中的抽象方法"));
}
}
2、函数式接口作为返回值类型
public static Comparator<String> getComparator() {
// 返回匿名函数
/* return new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return o2.length() - o1.length();
}
}; */
// 返回一个lambda表达式
/* return (String o1, String o2)-> {
return o2.length() - o1.length();
};*/
return (o1, o2) -> o2.length() - o1.length();
}
3、函数式接口作为参数
public class Demo01Runnable {
public static void startThread(Runnable run) {
new Thread(run).start(); // 开启多线程
}
public static void main(String[] args) {
// 匿名函数
startThread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "线程启动了");
}
});
// lambda表达式
startThread(()->System.out.println(Thread.currentThread().getName() + "线程启动了"));
}
}
4、Supplier接口
java.util.function.Supplier<T>接口仅包含一个参数的方法:T get(),用来获取一个泛型参数指定类型的对象数据
Supplier<T>接口被称之为生产型接口
public class Demo01Supplier {
// 定义一个方法,方法的参数传递Supplier<T>接口,泛型执行String,get方法就会返回一个String
public static String getString(Supplier<String> sup) {
return sup.get();
}
public static void main(String[] args) {
// 调用getString方法,方法的参数Supplier是一个函数式接口,所以可以传递Lambda表达式
System.out.println(getString(()-> "ss"));
}
}
5、Consumer接口
java.util.function.Consumer<T>接口则正好与Supplier接口相反,
它不是生产一个数据,而是消费一个数据,其数据类型由泛型决定。
Consumer接口中包含抽象方法void accept(T t),意为消费一个指定泛型的数据。
Consumer接口是一个消费型接口,泛型执行什么类型,就可以使用accept方法消费什么类型的数据
至于具体怎么消费(使用),需要自定义(输出,计算....)
public class Demo01Consumer {
public static void main(String[] args) {
method("明细", (String name)->{
// 翻转字符串
String s = new StringBuilder(name).reverse().toString();
System.out.println(s);
});
}
// 传递一个字符串的姓名
public static void method(String name, Consumer<String> con) {con.accept(name);}
}
1、Consumer接口的默认方法andThen
作用:需要两个Consumer接口,可以把两个Consumer接口组合到一起,在对数据进行消费
例如:
Consumer<String> con1
Consumer<String> con2
String s = "hello";
con1.accept(s);
con2.accept(s);
连接两个Consumer接口 再进行消费
con1.andThen(con2).accept(s); 谁写前边谁先消费
public class Demo02AndThen {
public static void main(String[] args) {
method("Hello",
(t)->{System.out.println(t.toLowerCase());},
(t)->{System.out.println(t.toUpperCase());});
}
public static void method(String s, Consumer<String>con1, Consumer<String>con2) {
// con1.accept(s);
// con2.accept(s);
// 使用andThen方法,把两个Consummer接口连接到一起,在消费数据
con1.andThen(con2).accept(s); // con1连接con2,先执行con1消费数据,在执行con2消费数据
}
}
2、练习,利用Consumer打印数组中的年龄性别
public class Demo03Test {
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) {
String[] arr = {"下面,女", "上面,男", "左面,女", "右面,男"};
printInfo(arr, (msg)->{
String name = msg.split(",")[0];
System.out.print("姓名:" + name + ",");
},(msg)->{
String name = msg.split(",")[1];
System.out.println("性别:" + name);
});
}
}
/*
姓名:下面,性别:女
姓名:上面,性别:男
姓名:左面,性别:女
姓名:右面,性别:男
*/
6、Predicate
java.util.function.Predicate<T>接口
作用:对某种数据类型的数据进行判断,结果返回一个boolean值
Predicate接口中包含一个抽象方法:
boolean test(T t):用来对指定数据类型数据进行判断的方法
结果:
符合条件,返回true
不符合条件,返回false
public class Demo01Predicate {
public static void main(String[] args) {
String s = "abcd";
boolean b = checkString(s, (str)-> {
return str.length() > 5; // 判断传入的字符串是否大于5
});
}
public static boolean checkString(String s, Predicate<String> pre) {
return pre.test(s);
}
}
1、默认方法:and
Predicate接口中有一个方法and,表示并且关系,也可以用于连接两个判断条件
/*
default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> this.test(t) && other.test(t);
}
*/
public class Dem02Predicate_and {
public static void main(String[] args) {
String s = "abcdef";
boolean b = checkString(s, (str)->{
return str.length() > 5;
}, (str)->{
return str.contains("a");
});
System.out.println(b);
}
public static boolean checkString(String s, Predicate<String> pre1, Predicate<String>pre2) {
// return pre1.test(s) && pre2.test(s);
return pre1.and(pre2).test(s);
}
}
2、默认方法:or
Predicate接口中有一个方法or,表示或者关系,也可以用于连接两个判断条件
public class Demo03Predicate_or {
public static void main(String[] args) {
String s = "abcdef";
boolean b = checkString(s, (str)->{
return str.length() > 5;
}, (str)->{
return str.contains("s");
});
System.out.println(b);
}
public static boolean checkString(String s, Predicate<String> pre1, Predicate<String>pre2) {
// return pre1.test(s) || pre2.test(s);
return pre1.or(pre2).test(s);
}
}
3、默认方法:negate
Predicate接口中有一个方法negate,也表示取反的意思
public class Demo04Predicate_negate {
public static void main(String[] args) {
String s = "abcdef";
boolean b = checkString(s, (str)-> {
return str.length() > 5;
});
System.out.println(b);
}
public static boolean checkString(String s, Predicate<String> pre) {
//return !pre.test(s);
return pre.negate().test(s);
}
}
4、练习:集合信息筛选
请通过Predicate接口的拼装将符合要求的字符串筛选到集合ArrayList中,
需要同时满足两个条件:
- 必须为女生;
- 姓名为3个字。
public class Demo05Test {
public static void main(String[] args) {
String[] arr = {"刘德华,男", "周华健,男", "张惠妹,女"};
ArrayList<String> list = filter(arr, (s)->{
return s.split(",")[1].equals("女");
}, (s)->{
return s.split(",")[0].length() == 3;
});
System.out.println(list);
}
public static ArrayList<String> filter(String[] arr, Predicate<String>pre1, Predicate<String>pre2) {
ArrayList<String> list = new ArrayList<>();
for (String s : arr) {
// 使用predicate接口中的方法test对获取到的字符串进行判断
boolean b = pre1.and(pre2).test(s);
if (b) {
list.add(s);
}
}
return list;
}
}
7、Function接口
java.util.function.Function<T,R>接口用来根据一个类型的数据得到另一个类型的数据,
前者称为前置条件,后者称为后置条件。
Function接口中最主要的抽象方法为:R apply(T t),根据类型T的参数获取类型R的结果。
使用的场景例如:将String类型转换为Integer类型。
public class Demo01Function {
public static void change(String s, Function<String, Integer> fun) {
Integer in = fun.apply(s);
System.out.println(in);
}
public static void main(String[] args) {
String s = "1234";
change(s, (String str)->{
return Integer.parseInt(str);
});
change(s, str->Integer.parseInt(str));
}
}
1、默认方法:andThen
Function接口中的默认方法andThen:用来进行组合操作
public class Demo2Function {
public static void change(String s, Function<String, Integer> fun1, Function<Integer, String> fun2) {
String str = fun1.andThen(fun2).apply(s);
System.out.println(str);
}
public static void main(String[] args) {
String s = "123";
change(s,(str)-> {
return Integer.parseInt(str) + 10;
}, (i)-> {
return i.toString();
});
}
}
网友评论