Lambda表达式
就是函数式编程是Java的新技术,是一种新的设计思想,目的是为了简化代码!!, 面向对象过分强调“必须通过对象的形式来做事情”,而函数式思想则尽量忽略面向对象的复杂语法——强调做什么,而不是以什么形式做:要干嘛就干嘛!!就是为了可以简化代码!
Lambda表达式的简化格式(重点):(形参列表) -> { //被简化的匿名内部类对象中,重写方法的方法体代码 }
格式解析: (形参列表):与被重写方法的形参列表一模一样。 -> 是一个新语法,无实现含义,只是指向重写方法的方法体代码。
{} 被简化的匿名内部类对象中,重写方法的方法体代码
Lambda表达式简化Runnable接口的匿名内部类写法。 点进Runnable接口中去,发现只有一个抽象方法、
并且有 @FunctionalInterface (函数式接口的注解)。有了这个注解的接口就是函数式接口,这个接口有且仅有一个抽象方法。
举例子:
public class LambdaDemo04 {
public static void main(String[] args) {
List<Student> stus = new ArrayList<>();
stus.add(new Student("白文波",21,"101期"));
stus.add(new Student("李涛涛",23,"97期"));
stus.add(new Student("常浩",18,"97期"));
System.out.println(stus);
// 按照年龄由小到大排序。
/* Collections.sort(stus, new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.getAge() - o2.getAge();
}
});*/
// Lambda表达式简化函数式接口的匿名内部类写法
Collections.sort(stus, (Student o1, Student o2) ->{
return o1.getAge() - o2.getAge();
});
Collections.sort(stus, ( o1, o2) ->{
return o1.getAge() - o2.getAge();
});
Collections.sort(stus, ( o1, o2) -> o1.getAge() - o2.getAge() );
System.out.println(stus);
}
}
常见的函数式接口有以下
supplier接口:函数式接口。 生产结果数据返回:生产者接口。
public class SupplierDemo01 {
public static void main(String[] args) {
/* Supplier<String> supplier = new Supplier<String>() {
@Override
public String get() {
return "欢迎徐干";
}
};
// 简化代码
Supplier<String> supplier1 = () -> "欢迎徐干";
System.out.println(supplier1.get());*/
/* add(new Supplier<String>() {
@Override
public String get() {
return "李四";
}
}, new Supplier<String>() {
@Override
public String get() {
return "王五";
}
});
*/
add(()->"李四" , ()->"王五");
//add(()->"徐干" , ()->"白文波");
}
public static void add(Supplier<String> p1 , Supplier<String> p2){
System.out.println(p1.get() + "=>" + p2.get());
}
}
public class SupplierExecDemo02 {
public static void main(String[] args) {
//(2)创建一个Supplier对象生产一个最大值传给printMax方法。
/* printMax(new Supplier<Integer>() {
@Override
public Integer get() {
int[] arrs = new int[]{100,23,999,2};
// 求出数组的最大值。
int max = arrs[0];
for(int ele : arrs){
if(ele > max){
max = ele;
}
}
return max; // 提供最大值
}
});*/
printMax(() -> {
int[] arrs = new int[]{100,23,999,2};
// 求出数组的最大值。
int max = arrs[0];
for(int ele : arrs){
if(ele > max){
max = ele;
}
}
return max; // 提供最大值
});
}
//(1)先定义一个方法去获取数组的最大值。
public static void printMax(Supplier<Integer> p1){
int max = p1.get() ; // 取出最大值
System.out.println("最大值输出:"+max);
}
}
Consumer接口:是用来消费数据的,根Supplier是相反的。
下列展示3个例子
public class ConsumerDemo01 {
public static void main(String[] args) {
//注释
/* Consumer<String> c = new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s.toUpperCase());
}
} ;
c.accept("itheima");*/
conYouData(s -> System.out.println(s.toUpperCase()),"itheima");
conYouData(s -> System.out.println(s.toLowerCase()),"itheimaABCD");
conYouData(s -> System.out.println(s.length()),"itheimaABCD");
}
public static void conYouData(Consumer<String> p1 ,String data){
p1.accept(data);
}
}
Consumer中的抽象方法:
void accept(T t):用来接收数据,消费数据的。
andThen:消费完一个数据以后然后继续消费。
andThen使用需求:
需求: 我给你一个字符串,请先以大写的形式输出,然后以小写的形式输出。
*/
public class ConsumerDemo02 {
public static void main(String[] args) {
printStr(s -> System.out.println(s.toUpperCase()) ,
s -> System.out.println(s.toLowerCase()) ,
"HelloWord");
}
public static void printStr(Consumer<String> p1 , Consumer<String> p2 , String data){
/**
* default Consumer<T> andThen(Consumer<? super T> after) {
return (T t) -> {
this.accept(t); // p1.accept(HelloWord);
after.accept(t);// p2.accept(HelloWord);
};
}
*
* */
p1.andThen(p2).accept(data);
}
}
public class ExecDemo03 {
public static void main(String[] args) {
String[] arrs = {"古力娜扎,女" , "迪丽热巴,女" , "马尔扎哈,男"};
Consumer<String> p1 = s -> System.out.print(s.split(",")[0]+"=");
Consumer<String> p2 = s -> System.out.println(s.split(",")[1]);
forEach(arrs ,p1 , p2 );
}
// 写一个方法负责,接收数据
public static void forEach(String[] datas, Consumer<String> p1, Consumer<String> p2){
for(String data : datas){
// data : 古力娜扎,女
p1.andThen(p2).accept(data);
}
}
}
输出结果:
古力娜扎=女
迪丽热巴=女
马尔咋哈=男
Function: 功能接口,工厂接口:你给我原材料,我生产结果给你。
下列展示2个例子
public class FuncationDemo01 {
public static void main(String[] args) {
// 需求:请帮我把"23",乘以二倍返回。
/*
Function<String , Integer> f1 = new Function<String, Integer>() {
@Override
public Integer apply(String s) {
return 2 * Integer.valueOf(s);
}
};
*/
Function<String , Integer> f1 = s -> 2 * Integer.valueOf(s);
System.out.println(f1.apply("23"));
}
}
抽象方法:
R apply(T t);
T:原材料的数据类型
R:结果数据的类型
默认方法:
andThen:完成功能以后然后继续完成另一个功能。
重点:把第一个功能的结果作为第二个功能的原材料。
需求:我现在给你一个字符串数字“23”,希望先转成整数*2,接下来输出“结果是46”
*/
public class FuncationDemo02 {
public static void main(String[] args) {
// 功能1:把字符串转成整数*2
// 原材料是字符串,结果是整数,
Function<String , Integer> p1 = s -> 2 * Integer.valueOf(s); // "23"-> 46
// 功能2:功能1的结果46传输给功能2 , 把整数的结果46输出成“结果是46”
// 原材料是Integer,结果是字符串。
Function<Integer,String> p2 = s -> "和是:"+s; // 46 -> "和是46"
// 功能3 :把“和是46”转换成“黑马输出了和是46”
// 原材料是字符串,结果是字符串。
Function<String,String> p3 = s -> "黑马输出了"+s; // "和是46" -> 黑马输出了和是46
fun(p1 , p2 , p3, "23");
}
public static void fun(Function<String , Integer> p1 ,
Function<Integer,String> p2 ,
Function<String,String> p3,
String data){
/**
* default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
return (T t) -> after.apply(apply(t));
// p2.apply(p1.apply("23"));
}
*
* */
String rs = p1.andThen(p2).andThen(p3).apply(data);
System.out.println(rs);
}
}
Predicate接口: 条件判断有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。这时可以使用
下列展示4个例子
抽象方法:
boolean test(T t);
给一个数据返回真或者假。
*/
public class PredicateDemo01 {
public static void main(String[] args) {
/* Predicate<String> p1 = new Predicate<String>() {
@Override
public boolean test(String s) {
return s.length() >= 6;// 校验密码
}
};*/
Predicate<String> p1 = s -> s.length() >= 6 ;
System.out.println(p1.test("admin123"));
}
}
Predicate接口的默认方法:
* 可以实现条件中的 与&& 或|| 非! 判断。
* 通过默认方法去实现的。
* 默认方法:
* and:实现与关系条件判断。
* default Predicate<T> and(Predicate<? super T> other) {
Objects.requireNonNull(other);
return (t) -> test(t) && other.test(t);
}
需求:
判断某个名字是否以张开始,并且长度是否>2.
分析:两个条件。
*
* */
public class PredicateDemo02 {
public static void main(String[] args) {
checkName(s -> s.startsWith("张"), s -> s.length() > 2, "张三丰");
}
public static void checkName(Predicate<String> p1 , Predicate<String> p2
, String name){
/**
* default Predicate<T> and(Predicate<? super T> other) {
return (t) -> this.test(t) && other.test(t);
// p1.test("张三丰") && p2.test("张三丰");
}
* */
System.out.println(p1.and(p2).test(name));
}
}
需求:姓名可以姓张,或者姓徐都满足。
*
* */
public class PredicateDemo03 {
public static void main(String[] args) {
checkName(s-> s.startsWith("张"), s -> s.startsWith("徐"),"干张徐");
}
public static void checkName(Predicate<String> p1 ,
Predicate<String> p2,String name){
/**
default Predicate<T> or(Predicate<? super T> other) {
return (t) -> test(t) || other.test(t);
// return p1.test("干张徐") || p2.test("干张徐");
}
* */
System.out.println(p1.or(p2).test(name));
}
}
默认方法:
非:negate
default Predicate<T> negate() {
return (t) -> !test(t);
}
需求:如果名字是以猪开始那么就返回false。
*
* */
public class PredicateDemo04 {
public static void main(String[] args) {
checkName(s -> s.startsWith("猪") , "猪八戒");
}
public static void checkName(Predicate<String> p1 ,
String name){
/**
* default Predicate<T> negate() {
return (t) -> !test(t);
// !p1.test("猪八戒")
}
*
* */
System.out.println(p1.negate().test(name));
// System.out.println(!p1.test("猪八戒"));
}
}