Lambda表达式
回顾Lambda表达式,当接口或抽象类只有一个抽象方法时可以使用Lambda表达式实现方法,精简语句。
线程的创建:
public class Demo01Runnable {
public static void startThread(Runnable run) {
new Thread(run).start();
}
public static void main(String[] args) {
startThread(() -> System.out.println(Thread.currentThread().getName() + "线程启动了"));
}
}
在排序中自定义比较规则:
public class Demo02Comparator {
public static Comparator<String> getComparator(){
return (o1, o2) -> o2.length() - o1.length();
}
public static void main(String[] args) {
String[] arr = {"aa", "bbb", "ddd"};
Arrays.sort(arr, getComparator());
System.out.println(Arrays.toString(arr));
}
}
函数式接口
只有一个抽象方法的接口称为函数式接口,可以用注解@FunctionalInterface显式表明这是一个函数式接口:
@FunctionalInterface //检测接口是否函数式接口
public interface MyFunctionalInterface {
public abstract void method();
//void method2();
}
在某些场景下使用函数式接口配合Lambda表达式可以节省性能:
public class Demo01Logger {
/*
以下代码存在一些性能浪费的问题
调用showLog方法,传递的第二个参数是一个拼接后的字符串
先把字符串拼接好,然后再调用showLog方法
如果level != 1,拼接操作就会造成性能浪费
*/
//定义一个根据日志的级别显示日志信息的方法
public static void showLog(int level, String message){
//对日志的登集进行判断,如果是1级别,输出日志信息
if(level == 1)
System.out.println(message);
}
public static void main(String[] args) {
//定义三个日志信息
String msg1 = "Hello";
String msg2 = "World";
String msg3 = "Java";
//调用showLog方法
showLog(1, msg1 + msg2 + msg3);
}
}
利用Lambda表达式节省性能:
先定义一个函数式接口:
@FunctionalInterface
public interface MessageBuilder {
String buildMessage();
}
利用Lambda表达式改进:
public class Demo02Lambda {
//定义一个显示日志的方法,方法的参数传递日志的等级和MessageBuilder接口
public static void showLog(int level, MessageBuilder mb){
if(level == 1){
System.out.println(mb.buildMessage());
}
}
public static void main(String[] args) {
String msg1 = "Hello";
String msg2 = "World";
String msg3 = "Java";
/*
使用Lambda表达式作为参数传递,仅仅把参数传递到showLog方法中
只有满足条件,才会进行字符串的拼接
*/
showLog(1, () -> {
System.out.println("level == 1, 字符串拼接");
return msg1 + msg2 + msg3;
});
}
}
常用函数式接口
Supplier
java.util.function.Supplier接口仅包含一个无参的方法:T get()。用来获取一个泛型参数指定类型的对象数据。
Supplier接口被称之为生产型接口,指定接口的泛型是什么类型,那么接口的get方法就产生什么类型的数据。
public class Demo01Supplier {
public static String getString(Supplier<String> sup){
return sup.get();
}
public static void main(String[] args) {
String s = getString(() -> "hello!");
}
}
使用示例:获取数组的最大值
public class Demo02Test {
public static int getMax(Supplier<Integer> sup){
return sup.get();
}
public static void main(String[] args) {
int[] arr = new int[]{2,6,1,6,4,8};
int max = getMax(() -> {
int temp = arr[0];
for (int e : arr) {
if(e > temp)
temp = e;
}
return temp;
});
System.out.println(max);
}
}
Consumer
和上述Supplier类似,但Consumer接口消费数据。
public class Demo01Consumer {
public static void consume(String name, Consumer<String> consumer){
consumer.accept(name);
}
public static void main(String[] args) {
String name = "Bob";
consume(name, (s) -> System.out.println(new StringBuilder(s).reverse()));
}
}
AndThen方法的使用:
public class Demo02AndThen {
public static void consume(String s, Consumer<String> con1, Consumer<String> con2){
/*con1.accept(s);
con2.accept(s);*/
con1.andThen(con2).accept(s); //先写谁谁先消费数据
}
public static void main(String[] args) {
String s = "Bob";
consume(s, (o) -> System.out.println(o.toLowerCase()),
(o) -> System.out.println(o.toUpperCase()));
}
}
使用示例:
第一个Consumer打印名字,第二个Consumer打印性别。
public class Demo03Test {
public static void printInfo(String[] arr, Consumer<String> con1, Consumer<String> con2){
for (String s : arr) {
con1.andThen(con2).accept(s);
}
}
public static void main(String[] args) {
String[] arr ={"Bob,male", "John,male", "Lana,female"};
printInfo(arr, (o) -> {
String name = o.split(",")[0];
System.out.print("Name: " + name + " ");
}, (o) -> {
String gender = o.split(",")[1];
System.out.println("Gender: " + gender);
});
}
}
Predicate
Predicate类用于进行逻辑判断,它的test方法返回boolean类型。
public class Demo01Predicate {
public static boolean checkString(String s, Predicate<String> pre){
return pre.test(s);
}
public static void main(String[] args) {
String s = "Valar Morghulis";
boolean isPanlindrome = checkString(s, (o) -> {
int left = 0, right = o.length() - 1;
while(left < right)
if(o.charAt(left) != o.charAt(right)) {
return false;
}
return true;
});
System.out.println(isPanlindrome);
}
}
Predicate有and、or、nagate三个方法:
public class Demo02Predicate_And {
//and
public static boolean checkString1(String s, Predicate<String> pre1, Predicate<String> pre2){
//return pre1.test(s) && pre2.test(s);
return pre1.and(pre2).test(s);
}
//or
public static boolean checkString2(String s, Predicate<String> pre1, Predicate<String> pre2){
return pre1.or(pre2).test(s);
}
//negate
public static boolean checkString3(String s, Predicate<String> pre1, Predicate<String> pre2){
return pre1.or(pre2).negate().test(s);
}
public static void main(String[] args) {
String s = "Predicate And";
boolean b1 = checkString1(s, (o) -> o.length() > 5, (o) -> {
int left = 0, right = o.length() - 1;
while(left < right)
if(o.charAt(left) != o.charAt(right)) {
return false;
}
return true;
});
boolean b2 = checkString2(s, (o) -> o.length() > 5, (o) -> {
int left = 0, right = o.length() - 1;
while(left < right)
if(o.charAt(left) != o.charAt(right)) {
return false;
}
return true;
});
System.out.println(b1); //false
System.out.println(b2); //true
}
}
使用示例:
public class Demo03Test {
public static ArrayList<String> filter(String[] arr, Predicate<String> pre1, Predicate<String> pre2){
ArrayList<String> res = new ArrayList<>();
for (String s : arr) {
if(pre1.and(pre2).test(s)){
res.add(s);
}
}
return res;
}
public static void main(String[] args) {
String[] arr ={"Bob,male", "John,male", "Lana,female"};
ArrayList<String> res = filter(arr, (o) -> {
String gender = o.split(",")[1];
return gender.equals("male");
}, (o) -> {
String name = o.split(",")[0];
return name.length() >= 4;
});
System.out.println(res.toString());
}
}
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){
int n = fun.apply(s);
System.out.println(n);
}
public static void main(String[] args) {
String s = "168530";
change(s, (o) -> Integer.parseInt(s));
}
}
Function中的andThen方法:
public class Demo02AndThen {
public static void change(String s, Function<String, Integer> fun1, Function<Integer, Integer> fun2){
System.out.println(fun1.andThen(fun2).apply(s));
}
public static void main(String[] args) {
String num = "1265";
change(num, o -> Integer.parseInt(num), o -> o + 10);
}
}
使用示例:
public class Demo03Test {
public static void method(String s, Function<String, String> f1, Function<String, Integer> f2, Function<Integer, Integer> f3){
System.out.println(f1.andThen(f2.andThen(f3)).apply(s));
}
public static void main(String[] args) {
String s = "Bob,22";
method(s, o -> o.substring(o.indexOf(",") + 1), o -> Integer.parseInt(o), o -> o + 100);
}
}