学习Java第三十五天--JDK8之Lambda表达式

18.JDK8

18.1 Lambda表达式

18.1.1 什么是Lambda表达式

  • 概念:允许把函数作为一个方法的参数。(函数作为参数传递到方法中)
    <函数式接口> <变量名> = (参数1 , 参数2 …) -> {
    //方法体
    }
public class TestLambdas {

	public static void main(String[] args) {
		
		//1.匿名内部类会生成.class文件
		Thread t1 = new Thread(new Runnable() {

			@Override
			public void run() {
				System.out.println("这是一个子线程");
			}
			
		});
		t1.start();
		
		//lambda表达式简写,不会生成单独的内部类文件
		Runnable task = () -> {
			System.out.println("这个也是一个子线程");
		};
		Thread t2 = new Thread(task);
		t2.start();
		
		new Thread( () -> {
			System.out.println("这个还是一个子线程");
		} ).start();
	}
	
}

输出结果:

这是一个子线程
这个也是一个子线程
这个还是一个子线程

18.1.2 注意事项

  • 新的操作符 -> (箭头操作符)
    (参数1 , 参数2) -> 表示参数列表
    -> { }方法体

  • 形参列表的数据类型会自动推动

  • 如果形参列表为空,只需保留()

  • 如果形参只有1个,()可以省略,只要参数名字即可

  • 如果执行语句只有1句,且无返回值,{}可以省略;

  • 若有返回值,仍想省略{},return也省略。保证执行语句只有1句

  • Lambda表达式不会生成单独的内部类文件

  • Lambda访问局部变量时,变量要修饰final,如果没加,会自动添加

员工类:

public class Employee {

	private String name;
	private int age;
	private String sex;
	private double salary;
	
	public Employee() {
		super();
	}

	public Employee(String name, int age, String sex, double salary) {
		super();
		this.name = name;
		this.age = age;
		this.sex = sex;
		this.salary = salary;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getSex() {
		return sex;
	}

	public void setSex(String sex) {
		this.sex = sex;
	}

	public double getSalary() {
		return salary;
	}

	public void setSalary(double salary) {
		this.salary = salary;
	}

	@Override
	public String toString() {
		return "Employee [name=" + name + ", age=" + age + ", sex=" + sex + ", salary=" + salary + "]";
	}
	
}

断言型接口:

/*
 * 规则
 * 能力
 * */

//需求只是需要对关键信息进行判断,返回布尔值,则可以为其定义普适性的接口
public interface MyPredicate<T> {
	boolean test(T t);
}
import java.util.ArrayList;
import java.util.List;

public class TestEmployee {

	public static void main(String[] args) {
		List<Employee> list = new ArrayList<Employee>();
		list.add(new Employee("Tom",32,"male",28000));
		list.add(new Employee("Jack",25,"male",18000));
		list.add(new Employee("Alex",22,"male",13000));
		list.add(new Employee("Annie",21,"female",9000));
		list.add(new Employee("Rose",20,"male",8000));
		
		//获得年龄大于等于25的员工
//		List<Employee> ageList = getAgeEmployee(list);
//		for (Employee e : ageList) {
//			System.out.println(e);
//		}
//		System.out.println();
		
		//获得工资大于10000的员工
//		List<Employee> salaryList = getSalaryEmployee(list);
//		for (Employee e : salaryList) {
//			System.out.println(e);
//		}
//		System.out.println();
//基本的实现需求的操作
		
		
		//获得年龄大于25且工资大于10000的员工	通过普适性的方法实现需求
		List<Employee> prelist = getAgeAndSalary(list,new MyPredicate<Employee>() {

			@Override
			public boolean test(Employee t) {
				if(t.getAge() >= 25 && t.getSalary() >= 10000) {
					return true;
				}
				return false;
			}
			
		});
		for (Employee employee : prelist) {
			System.out.println(employee);
		}
		System.out.println();
		
		
		System.out.println("----lambda 工资大于等于10000年龄大于等于25----");
		//使用lambda表达式可以简写为
		List<Employee> prelist2 = getAgeAndSalary(list, (e) ->{
			return e.getAge()>=25 && e.getSalary()>=10000;
		});
		//甚至还能简写为
		List<Employee> prelist3 = getAgeAndSalary(list, e -> e.getAge() >= 25 && e.getSalary() >= 10000);
		for (Employee employee : prelist2) {
			System.out.println(employee);
		}
		System.out.println("-------------------------------------\n");
		
		
		//使用普适性接口和lambda表达式简写最上面两个
		System.out.println("---lambda 年龄大于等于25的---");
		List<Employee> prelist4 = getAgeAndSalary(list, (e) -> {//通用的简写方式
			return e.getAge()>=25;		
		});
		for (Employee employee : prelist4) {
			System.out.println(employee);
		}
		System.out.println();
		
		System.out.println("---lambda 工资大于等于10000的---");
		//当形参只有一个,且执行语句只有一句,则可以省略()  {;}
		List<Employee> prelist5 = getAgeAndSalary(list, e ->  e.getSalary()>=10000);
		for (Employee employee : prelist5) {
			System.out.println(employee);
		}
		System.out.println();
		
		
		
		//stream简写,更加简化。。。
		System.out.println("-------------stream相关的实现输出工资大于等于10000的-----------------");
		list.stream().filter( (e)->e.getSalary() >= 10000 ).forEach(System.out::println);
	
	
	}
	
	//实现需求的普通的写法
//	public static List<Employee> getAgeEmployee(List<Employee> list){
//		
//		List<Employee> newlist = new ArrayList<>();
//		for(Employee e : list) {
//			if(e.getAge() >= 25) {
//				newlist.add(e);
//			}
//		}
//		return newlist;
//	}
	
//	public static List<Employee> getSalaryEmployee(List<Employee> list){
//		
//		List<Employee> newlist = new ArrayList<>();
//		for(Employee e : list) {
//			if(e.getSalary() >= 10000) {
//				newlist.add(e);
//			}
//		}
//		return newlist;
//	}
	
	//使用Predicate接口实现 对不同需求的通用方法
	public static List<Employee> getAgeAndSalary(List<Employee> list , MyPredicate<Employee> predicate){
		List<Employee> newlist = new ArrayList<>();
		for (Employee e : list) {
			if(predicate.test(e)) {//调用规则!只关心结果,不关心过程
				newlist.add(e);
			}
		}
		return newlist;
	}
	
}

输出结果:

Employee [name=Tom, age=32, sex=male, salary=28000.0]
Employee [name=Jack, age=25, sex=male, salary=18000.0]

----lambda 工资大于等于10000年龄大于等于25----
Employee [name=Tom, age=32, sex=male, salary=28000.0]
Employee [name=Jack, age=25, sex=male, salary=18000.0]
-------------------------------------

---lambda 年龄大于等于25---
Employee [name=Tom, age=32, sex=male, salary=28000.0]
Employee [name=Jack, age=25, sex=male, salary=18000.0]

---lambda 工资大于等于10000---
Employee [name=Tom, age=32, sex=male, salary=28000.0]
Employee [name=Jack, age=25, sex=male, salary=18000.0]
Employee [name=Alex, age=22, sex=male, salary=13000.0]

-------------stream相关的实现输出工资大于等于10000-----------------
Employee [name=Tom, age=32, sex=male, salary=28000.0]
Employee [name=Jack, age=25, sex=male, salary=18000.0]
Employee [name=Alex, age=22, sex=male, salary=13000.0]

18.1.3 函数式接口

  • 如果一个接口只有一个抽象方法,则该接口称为函数式接口;
  • 为了确保接口达到要求,可以添加@FuntionalInterface注解;

内置四个核心函数式接口:

  • Consumer 消费型接口 void accept(T t);
import java.util.function.Consumer;

public class TestConsumer {

	public static void main(String[] args) {
		m1(1000,(a)->System.out.println("今天挣了:"+a+"rmb"));

		m2(10 , (a)->{
			for(int i = 1;i<=a;i++) {
				System.out.println(i);
			}
		});
	}
	
	//Consumer接口是只有一个 无返回值,单个形参 的接口,可用于使用lambda表达式
	public static void m1(double money , Consumer<Double> consumer) {
		consumer.accept(money);
	}
	public static void m2(int num , Consumer<Integer> consumer) {
		consumer.accept(num);
	}
}

输出结果:

今天挣了:1000.0rmb
1
2
3
4
5
6
7
8
9
10
  • Supplier 共计型接口 T get();
import java.util.Random;
import java.util.function.Supplier;

public class TestSupplier {

	public static void main(String[] args) {
		
		//使用Supplier接口,实现一个通用型的方法,调用该方法时,可以使用lambda表达式进行简写
		int sum = getSum(10, ()->new Random().nextInt(100));
		System.out.println("的和是:"+sum);
		
		
		//使用Supplier接口和lambda表达式,进行自定义功能
		Supplier<Integer> sup = () -> {
			int count = 0 ;
			for(int i = 1 ; i<=50; i++) {
				count += i;
			}
			return count;
		};
		System.out.println("1~50的和是:"+ sup.get());
	}

	//Supplier接口是一个  有一个对象类型,无参的抽象方法  的接口
	public static int getSum(int num , Supplier<Integer> supplier) {
		int sum = 0 ;
		for(int i = 1 ; i<= num ; i++) {
			System.out.print(supplier.get()+" ");
			sum += supplier.get();
		}
		return sum;
	}
}

输出结果:

51 23 36 14 98 97 2 37 45 20 的和是:601
1~50的和是:1275
  • Function<T,R> 函数型接口 R apply(T t);
import java.util.function.Function;

public class TestFunction {

	public static void main(String[] args) {
		
		//使用Function接口,通过lambda表达式实现接口,自定义实现方法
		String up = stringUpper("hello" , (s) -> s.toUpperCase() );
		System.out.println(up);

		String tirms = stringUpper("  Alex   " , (s) -> s.trim());
		System.out.println(tirms);
	}

	//Function接口是一个 只有个形参、一个返回值的方法的 的接口。 
	//使用时,以Function<T,R>的形式使用,传入的形参是T,返回的是R,相当于对T进行操作,以R的形式返回
	public static String stringUpper(String s , Function<String ,String> fun) {
		return fun.apply(s);
	}
}

输出结果:

HELLO
Alex
  • Predicate 断言型接口 boolean test(T t);
import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate;

public class TestPredicate {

	public static void main(String[] args) {
		List<String> list = new ArrayList<String>();
		
		list.add("tom");
		list.add("jack");
		list.add("alex");
		list.add("rose");
		list.add("annie");
		
		//使用Predicate接口,通过lambda表达式,自定义过滤条件
		List<String> f = filter(list , (s) -> s.startsWith("a"));
		for (String s : f) {
			System.out.println(s);
		}
	}

	//Predicate接口是 只有一个  单参数、布尔类型返回值 的方法的接口
	public static List<String> filter(List<String> list , Predicate<String> p){
		List<String> list2 = new ArrayList<String>();
		for(String s : list) {
			if(p.test(s)) {
				list2.add(s);
			}
		}
		return list2;
	}
}

输出结果:

alex
annie

18.1.4 方法引用

  • 方法引用是Lambda表达式的一种简写形式,如果Lambda表达式方法体中只是调用一个特定的已存在的方法,则可以使用方法引用;
  • 使用 :: 操作符将对象或类和方法名的名字分隔开来;
    对象 :: 实例方法
    类 :: 静态方法
    类 :: 实例方法
    类 :: new
  • 注意:调用的方法参数列表与返回值 类型,要与函数型接口中的方法参数列表与返回值类型一致;
import java.util.Comparator;
import java.util.TreeSet;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Supplier;

import com.qf.Day35.Employee;



public class TestMethodRef {

	public static void main(String[] args) {
		
		//Lambda表达式简化了匿名内部类,方法引用简化了Lambda表达式
		
		//1.对象::方法名
			//平常的写法
		Consumer<String> con = (s) -> System.out.println(s);
		con.accept("hello");
			//使用方法引用的写法
		Consumer<String> con2 = System.out::println;
		con2.accept("world");
		
		Employee e = new Employee("alex" , 22 , "male" , 15000D);
		Supplier<String> sup1 = () -> e.getName();//lambda
		System.out.println(sup1.get());
		Supplier<String> sup2 = e::getName;//与上同理,方法引用的写法
		System.out.println(sup2.get());
		
		//2.类名::静态方法(不常用)
		Comparator<Integer> com = (x,y) -> Integer.compare(x,y);//lambda
		int result = com.compare(1, 2);
		System.out.println(result);
		Comparator<Integer> com2 = Integer::compare;//方法引用的写法
		
		TreeSet<Integer> ts = new TreeSet<>(com);//制定TreeSet的排序规则
		
		//3.类名::实例方法名
		//Function<T,R>  R.apply(T t);
		Function<Employee , String> fun = emp -> emp.getName(); //lambda
		String name = fun.apply(e);
		System.out.println(name);
		Function<Employee , String> fun2 = Employee::getName;//方法引用
		
		
		//4.类::new   类名::构造方法(不常用)
		Supplier<Employee> supp = () -> new Employee();//lambda
		Employee empl = supp.get();
		System.out.println(empl);
		Supplier<Employee> supp2 = Employee::new;//方法引用
	}

}

输出结果:

hello
world
alex
alex
-1
alex
Employee [name=null, age=0, sex=null, salary=0.0]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值