小知识点:
案例:
public class MyInterfaceDemo {
public static void main(String[] args) {
// 函数式接口可以用作方法的参数传递
// 是不是说Lambda表达式啊
useShow(()-> System.out.println("方法的参数传递"));
// 函数式接口用作局部变量
MyInterface my = () -> System.out.println("局部变量");
// 将Lambda表达式 赋值给 函数式接口
// 上述等价于
/* MyInterface my = new MyInterface() {
@Override
public void show() {
System.out.println("局部变量");
}
};*/
my.show();
}
private static void useShow(MyInterface mif){
mif.show();
}
}
如果方法的参数是一个函数式接口,可以使用Lambda表达式作为参数传递。
startThread(() -> System.out.println(Thread.currentThread().getName() + ""));
需求:
类(RunnableDemo),两个方法:startThread(Runnable r)方法参数Runnable是一个函数式接口;
main主方法,调用startThread方法
public class RunnableDemo {
public static void main(String[] args) {
// 调用startThread方法
// 匿名内部类的方式
startThread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "线程启动了");
}
});
// Lambda表达式 的方式
startThread(() -> System.out.println(Thread.currentThread().getName() + "线程启动了"));
}
private static void startThread(Runnable r){
/* Thread t = new Thread(r);
t.start();*/
// 简写
new Thread(r).start();
// 也就是线程的启动
}
}
如果方法的返回值是一个函数式接口,使用Lambda表达式作为结果返回。
匿名内部类:
private static Comparator<String> getComparator(){
return (s1,s2) -> s1.length()-s2.length();
}
需求:
类(ComparatorDemo),两个方法:
Comparator< String >getComparator() 方法返回值Comparator是一个函数式接口
主方法main,调用getComparator方法
public class ComparatorDemo {
/*
类(ComparatorDemo),两个方法:
Comparator< String >getComparator() 方法返回值Comparator是一个函数式接口
主方法main,调用getComparator方法
*/
public static void main(String[] args) {
// 创建集合,存储字符串字符
ArrayList<String> array = new ArrayList<String>();
array.add("cccc");
array.add("aa");
array.add("b");
array.add("ddd");
System.out.println("排序前:" + array);
// 输出内容是:排序前:[cccc, aa, b, ddd]
// 就是按照集合添加的顺序。
// 自然排序 按照自然排序。
Collections.sort(array);
System.out.println("排序后:" + array);
// 输出内容:排序后:[aa, b, cccc, ddd]
//
Collections.sort(array, getComparator());
System.out.println("排序后1:" + array);
}
private static Comparator<String> getComparator(){
// 返回值是Comparator的实现类对象
// 使用匿名内部类的形式
/* Comparator c = new Comparator(){
@Override
public int compare(String s1, String s2) {
return s1.length() - s2.length();
}
};
return c;*/
// 改进 省略 这里使用的是匿名内部类的方式。
// return new Comparator() {
// @Override
// public int compare(String s1, String s2) {
// return s1.length() - s2.length();
// // 正数 s1待比较数据 s2是已存在的数据
// // 也就是 长的数据放在后面
// }
// };
// 改进 使用Lambda表达式
// return (String s1,String s2) -> {
// return s1.length() - s2.length();
// };
// 省略形式
return (s1,s2) -> s1.length()-s2.length();
}
}
java 8 在java.util.function包下预定了大量的函数式接口供使用
四个接口: Supplier接口、Consumer接口、Predicate接口、Function接口。
接口名 | 说明 |
---|---|
Supplier< T > | 产生一个T类型的数据 |
Consumer< T > | 接收一个T类型的数据 |
Predicate< T > | 判断T类型的参数是否满足指定条件,返回boolean类型 |
Function< T,R > | 输入T类型的参数,输出R类型的参数,按照指定的操作完成 |
概述:
案例:
public class SupplierDemo {
public static void main(String[] args) {
// getString 方法的参数是函数式接口,那么实际上传递的是接口的实现类对象。
// 只有一个方法get,
// 匿名内部类形式
String st = getString(new Supplier<String>() {
@Override
public String get() {
return "you";
}
});
System.out.println(st);
// Lambda表达式形式
String s = getString(()->{
return "sunshine";
});
System.out.println(s);
// 省略
String name = getString(() -> "汪苏泷");
System.out.println(name);
Integer i = getInteger(() -> 30);
}
// 定义方法,返回一个字符串
private static String getString(Supplier<String> sup){
return sup.get();
}
// 定义方法,返回一个整数
private static Integer getInteger(Supplier<Integer> sup){
return sup.get();
}
}
练习:
需求:
类(SupplierTest),两个方法:int getMax(Supplier< Integer > sup)用于返回一个int数组中的最大值;
main方法 调用getMax方法。
public class SupplierTest {
public static void main(String[] args) {
/*
类(SupplierTest),两个方法:
int getMax(Supplier< Integer > sup)用于返回一个int数组中的最大值;
main方法 调用getMax方法。
*/
int[] array = {19,50,28,27,46};
int MaxValue = getMax(() -> {
int max = array[0];
for(int i = 1; i < array.length ; i++){
if(array[i] > max){
max = array[i];
}
}
return max;
});
System.out.println(MaxValue);
}
private static Integer getMax(Supplier<Integer> sup){
return sup.get();
// 具体的操作 还得Lambda表达式 进行设置
}
}
概念:
方法名 | 说明 |
---|---|
void accept(T t) | 对给定的参数执行此操作 此操作最终是在Lambda表达式中实现的 |
default Consumer< T > andThen(Consumer < ? super T > after) default Consumer< T > andThen (Consumer after) |
返回一个组成的Consumer,依次执行此操作,然后执行after操作 |
案例: |
public class ConsumerDemo {
public static void main(String[] args) {
// 调用operatorString方法
operatorString("汪苏泷", (String s)->{
System.out.println(s);
});
// 省略
operatorString("许嵩", s -> System.out.println(s));
// 方法引用的形式 引用类的方法 类::静态方法
operatorString("林俊杰", System.out::println);
// 将输出内容翻转
operatorString("周杰伦", s -> {
System.out.println(new StringBuilder(s).reverse().toString());
});
System.out.println("------------------");
operatorString1("胡夏", s-> System.out.println(s), s-> System.out.println(new StringBuffer(s).reverse().toString()));
}
// 定义方法,消费一个字符串
private static void operatorString(String name, Consumer<String> con){
con.accept(name);
// 具体的操作由Lambda表达式书写
}
// 定义方法 ,用不同的方式消费同一个字符串数据两次
// 也就是有两个Consumer接口
private static void operatorString1(String name,Consumer<String> con1,Consumer<String> con2){
// con1.accept(name);
// con2.accept(name);
// 使用andThen改进
con1.andThen(con2).accept(name);
/* default Consumer andThen(Consumer super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
*/
}
}
练习:
要求:
String[] strArray = {“汪苏泷,30”,“许嵩,32”,“胡夏,32”};
字符串数组中有多条信息,请按照格式:“姓名:xx,年龄:xx”的格式输出打印
把打印姓名的动作 第一个 Consumer 接口的Lambda实例
把打印年龄的动作 第二个 Consumer 接口的Lambda实例
将两个Consumer接口按照顺序组合到一起使用
public class ConsumerTest {
/*字符串数组中有多条信息,请按照格式:“姓名:xx,年龄:xx”的格式输出打印
把打印姓名的动作 第一个 Consumer 接口的Lambda实例
把打印年龄的动作 第二个 Consumer 接口的Lambda实例
将两个Consumer接口按照顺序组合到一起使用
*/
public static void main(String[] args) {
String[] strArray = {"汪苏泷,30","许嵩,32","胡夏,32"};
// 自己的
for(String str:strArray){
printNameAge(str, s -> {
String name = s.split(",")[0];
System.out.print("姓名:" + name);
},s->{
String age = s.split(",")[1];
System.out.println(",年龄:" + age);
});
}
System.out.println("---------------");
// 视频中的
printInfo(strArray, s->{
String name = s.split(",")[0];
System.out.print("姓名:" + name);
}, s->{
String age = s.split(",")[1];
System.out.println(",年龄:" + age);
});
}
// 自己的想法
private static void printNameAge(String str, Consumer<String> con1,Consumer<String> con2){
con1.andThen(con2).accept(str);
}
// 视频中想法
private static void printInfo(String[] strArray,Consumer<String> con1,Consumer<String>con2){
for(String str:strArray){
con1.andThen(con2).accept(str);
}
}
}
概念:
方法名 | 说明 |
---|---|
boolean test(T t) | 对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值 Predicate对象.test() |
default Predicate< T > negate() | 返回一个逻辑的否定,对应逻辑非 Predicate对象.negate().test() |
default Predicate< T > and(Predicate other) | 返回一个组合判断,对应短路与 Predicate对象1.and(Predicate对象2).test() |
default Predicate< T > or(Predicate other) | 返回一个组合判断,对应短路或 Predicate对象1.or(Predicate对象2).test() |
案例: |
public class PredicateDemo {
public static void main(String[] args) {
// 调用checkString方法
boolean b = checkString("sun",(String str)->{
return str.length() > 5;
});
System.out.println(b);
boolean b1 = checkString("sunshine", str -> str.length() > 5);
System.out.println(b1);
}
// 判断给定的字符串是否满足要求
private static boolean checkString(String s, Predicate<String> pre){
// return pre.test(s);
// 具体的实现在 调用它的Lambda表达式中实现
// 想实现逻辑非的操作
// return !pre.test(s);
// 不是使用上述形式,而是采用negate方法,且negate方法得在test方法之前
return pre.negate().test(s);
}
}
案例:
public class PredicateDemo2 {
public static void main(String[] args) {
boolean b1 = checkString("sun", s->s.length()>2);
System.out.println(b1);
boolean b2 = checkString("sunshine", s->s.length()<5);
System.out.println(b2);
System.out.println("--------------");
boolean b3 = checkStringAdd("hello", s->s.length()>6, s1 -> s1.length() <15);
System.out.println(b3);
}
// 同一个字符串做两个不同的判断,并将两个判断结果做逻辑与的结果作为最终输出结果
private static boolean checkStringAdd(String s ,Predicate<String> pre1,Predicate<String> pre2){
// boolean b1 = pre1.test(s);
// boolean b2 = pre2.test(s);
// boolean b = b1 && b2;
// return b;
// 实现短路与 可以使用方法and
// return pre1.and(pre2).test(s);
/*default Predicate and(Predicate super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}*/
// 实现短路或 可以使用方法or
return pre1.or(pre2).test(s);
/*default Predicate or(Predicate super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) || other.test(t);
}*/
}
// 判断给定字符串是否满足条件
private static boolean checkString(String s, Predicate<String> pre){
return pre.test(s);
}
}
练习:
需求:
String[] strArray = {“汪苏泷,30”,“许嵩,34”,“林俊杰,35”,“胡夏,31”,“周杰伦,33”};
字符串数组中有多条信息,请通过Predicate接口的拼接将符合要求的字符串筛选到集合ArrayList中,并遍历ArrayList集合
同时满足要求:姓名长度大于2;年龄大于33;
public class PredicateDemo3 {
public static void main(String[] args) {
String[] strArray = {"汪苏泷,30","许嵩,34","林俊杰,35","胡夏,31","周杰伦,33"};
// 自己写的方法:方法1
// ArrayList array = new ArrayList();
// for(String s:strArray){
// boolean b = checkName(s, (String s1) -> {
// String name = s1.split(",")[0];
// return name.length()>2;
// }, (String s2)->{
// int age = Integer.parseInt(s2.split(",")[1]);
// return age>33;
// });
// if(b){
// array.add(s);
// }
// }
// for(String s:array){
// System.out.println(s);
// }
// 方法2
ArrayList<String> arr = checkName2(strArray,(String s)->{
String name = s.split(",")[0];
return name.length() >2;
},(String s2)->{
int age = Integer.parseInt(s2.split(",")[1]);
return age>33;
});
for(String s:arr){
System.out.println(s);
}
}
// 自己写的 方法1
private static boolean checkName(String str, Predicate<String> pre1, Predicate<String> pre2){
return pre1.and(pre2).test(str);
}
// 通过Predicate接口的拼接将符合要求的字符串筛选到集合ArrayList中,并遍历ArrayList集合 方法2
private static ArrayList<String>checkName2(String[] strs,Predicate<String> pre1,Predicate<String> pre2){
// 定义集合
ArrayList<String> arr = new ArrayList<String>();
// 遍历String数组
for(String s:strs){
if(pre1.and(pre2).test(s)){
arr.add(s);
}
}
return arr;
}
}
概念:
方法名 | 说明 |
---|---|
R apply(T t) | 将此函数应用于给定的参数 |
default < V > Function andThen(Function after) | 返回一个组合函数,首先将该函数应用于输入,然后将after函数应用于结果 |
案例: |
public class FunctionDemo {
public static void main(String[] args) {
// 方法1
convertInt("1024", (String s)->{
return Integer.parseInt(s);
});
// 优化
convertInt("2048",s -> Integer.parseInt(s));
// 方法2
convertString(924, (Integer i)->{
return String.valueOf(i+100);
});
// 方法3 自己的
convertStrToIntToString("1022", s->{
return String.valueOf(Integer.parseInt(s) + 1000);
});
// 方法3 视频中的
convertStrToIntToString("1000", s->Integer.parseInt(s)+24,i->String.valueOf(i));
}
// 定义一个方法,把一个字符串转换为int类型,在控制台输出 方法1
private static void convertInt(String s, Function<String,Integer> fun){
Integer i = fun.apply(s);
System.out.println(i);
}
// 方法2 把一个int类型的数 加上一个整数之后,转为字符串在控制台输出
private static void convertString(Integer i,Function<Integer,String> fun){
String s = fun.apply(i);
System.out.println(s);
}
// 方法3 把一个字符串转为int类型,加上一个整数之后,转为字符串在控制台输出 自己的
private static void convertStrToIntToString(String st,Function<String,String> fun){
String str = fun.apply(st);
System.out.println(str);
}
// 方法3 把一个字符串转为int类型,加上一个整数之后,转为字符串在控制台输出 自己的
private static void convertStrToIntToString(String s,Function<String,Integer> fun1,Function<Integer,String> fun2){
// Integer i = fun1.apply(s);
// String ss = fun2.apply(i);
// System.out.println(ss);
// 使用andThen方法改进
String ss = fun1.andThen(fun2).apply(s);
System.out.println(ss);
/* default Function andThen(Function super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
*/
}
}
练习:
需求:
String s = “汪苏泷,30”;
操作:①字符串截取得到数字年龄部分;②将数字年龄字符串转为int类型的数据;③数据加70,在控制台输出
public class FunctionDemo2 {
public static void main(String[] args) {
String s = "汪苏泷,30";
// xhj
sumAge(s, s1 -> {
String age = s.split(",")[1];
return Integer.parseInt(age ) + 70;
});
// video
convert(s, s1 -> s.split(",")[1],s2 -> Integer.parseInt(s2), i -> i + 70);
}
// xhj
private static void sumAge(String s, Function<String,Integer> fun1){
Integer i = fun1.apply(s);
System.out.println(i);
}
// video
private static void convert(String s,Function<String,String> fun1,Function<String,Integer> fun2,Function<Integer,Integer> fun3){
Integer i = fun1.andThen(fun2).andThen(fun3).apply(s);
System.out.println(i);
}
}