Java8——Lambda表达式(1)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/rubulai/article/details/88721661
简介

  Lambda是Java8中支持的一种新的语法格式,Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为一段可以传递的代码(将代码像数据一样进行传递)。使用Lambda表达式可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。

示例

 需求:查询公司年龄大于35岁的员工信息
  实现方式一:提供一个专门的过滤方法

public class TestMain {

	//数据
	List<Employee> employees = new ArrayList<Employee>(Arrays.asList(
			new Employee("zhangsan", 24, 5050.00),
			new Employee("lisi", 58, 6666.00), 
			new Employee("wangwu", 32, 3333.00), 
			new Employee("xueliu", 43, 2222.00),
			new Employee("tianqi", 28, 7777.00), 
			new Employee("maer", 36, 8888.00)
		));
	
	/**
	 * 过滤年龄超过35岁的员工
	 * @param employees
	 * @return
	 */
	public List<Employee> filterEmpByAge(List<Employee> employees){
		List<Employee> emps = new ArrayList<>();
		for(Employee emp : employees)
			if(emp.getAge() > 35)
				emps.add(emp);
		
		return emps;
	}

	@Test
	public void test1(){
		//调用方法获取员工中年龄大于35的员工信息
		List<Employee> filterEmpByAge = filterEmpByAge(employees);
		for (Employee employee : filterEmpByAge) {
			System.out.println(employee);
			
		}
	}
}

 如果此时需求有变动,让查询工资大于5000的员工,则需要再专门提供一个使用工资进行过滤的方法:

/**
 * 工资超过5000的员工
 * @param employees
 * @return
 */
public List<Employee> filterEmpBySalary(List<Employee> employees){
	List<Employee> emps = new ArrayList<>();
	for(Employee emp : employees)
		if(emp.getSalary() > 5000)
			emps.add(emp);
	
	return emps;
}

 而需求是多变的,这样的话就可能会有很多类似的方法,而这些方法中只有一处不同,那就是过滤条件,其他地方完全一样,很明显这样会有很多的代码冗余。

  实现方式二:策略设计模式
   1、定义一个过滤的接口

public interface PredicateRule<T> {
	/**
	 * 返回符合条件的t
	 * 
	 * @param t
	 * @return
	 */
	public boolean test(T t);
}

   2、按照条件提供两个该接口的实现:

/**
 * 年龄大于35
 */
public class AgePredicateRule implements PredicateRule<Employee> {
	@Override
	public boolean test(Employee t) {
		return t.getAge() > 35;
	}
}

/**
 * 工资大于5000
 */
public class SalaryPredicateRule implements PredicateRule<Employee> {
	@Override
	public boolean test(Employee t) {
		return t.getSalary() > 5000;
	}
}

   3、提供一个公共的过滤方法:该方法会根据传入的PredicateRule的具体实现进行过滤

/**
 * 统一的过滤方法:会根据传入的PredicateRule的实现进行过滤
 * 
 * @param emps
 * @param rule
 * @return
 */
public List<Employee> filterEmpByRule(List<Employee> emps, PredicateRule<Employee> rule) {
	List<Employee> employees = new ArrayList<>();
	for (Employee employee : emps)
		if (rule.test(employee))
			employees.add(employee);

	return employees;
}

   4、使用:此时传入的是AgePredicateRule,则会过滤年龄超过35岁的员工

public void test2() {
	//此时传入的是AgePredicateRule,则会过滤年龄超过35岁的员工
	List<Employee> filterEmpByRule = filterEmpByRule(employees, new AgePredicateRule());
	for (Employee employee : filterEmpByRule) {
		System.out.println(employee);
	}
}

  实现方式三:匿名内部类,方式二中每增加一个查询条件都需要实现一次过滤接口,而且实现的方式中也只有一行代码是不同的,我们可以使用内名内部类的方式避免创建冗余的接口实现

/**
 * 统一的过滤方法:会根据传入的PredicateRule的实现进行过滤
 * 
 * @param emps
 * @param rule
 * @return
 */
public List<Employee> filterEmpByRule(List<Employee> emps, PredicateRule<Employee> rule) {
	List<Employee> employees = new ArrayList<>();
	for (Employee employee : emps)
		if (rule.test(employee))
			employees.add(employee);

	return employees;
}

@Test
public void test3() {
	//使用匿名内部类
	List<Employee> filterEmpByRule = filterEmpByRule(employees, new PredicateRule<Employee>() {
		@Override
		public boolean test(Employee t) {
			// 过滤年龄大于35岁的员工
			return t.getAge() > 35;
		}
	});
	
	for (Employee employee : filterEmpByRule) {
		System.out.println(employee);
	}
}

  这样虽然避免了频繁创建接口的实现导致的代码冗余,但影响了代码的可读性,且从一定程度上代码还是有冗余,因为过滤的核心代码只是条件而已

  鉴于以上种种弊端,Java8提供了Lambda表达式

/**
 * 统一的过滤方法:会根据传入的PredicateRule的实现进行过滤
 * 
 * @param emps
 * @param rule
 * @return
 */
public List<Employee> filterEmpByRule(List<Employee> emps, PredicateRule<Employee> rule) {
	List<Employee> employees = new ArrayList<>();
	for (Employee employee : emps)
		if (rule.test(employee))
			employees.add(employee);

	return employees;
}

@Test
public void test4() {
	List<Employee> filterEmpByRule = filterEmpByRule(employees, (e) -> e.getAge() > 35);
    filterEmpByRule.forEach(System.out::println);
}

   Lambda表达式实际上是一个匿名函数,该匿名函数会根据方法的入参自动推断出你要调用的方法,比如此时调用方法filterEmpByRule(List list,PredicateRule rule),我们在第二个参数的位置使用了Lambda表达式,那么Java8就会推断出来你要调用的是PredicateRule接口中的方法,Lambda表达式的小括号()中的内容表示调用该方法时传入的参数,箭头->后面的代码则表示方法的方法体,因此PredicateRule 接口只能定义一个抽象方法(这样的接口称为函数接口),否则Lambda在推断时将会出错,入参的类型则由泛型定义。
   可以看出使用Lambda表达式只需要写关键的代码即可,会大大的节省代码量。

  还可以使用Stream API作进一步精简:这样连接口和公共方法都不需要提供了

public class TestMain {

	// 数据
	List<Employee> employees = new ArrayList<Employee>(Arrays.asList(new Employee("zhangsan", 24, 5050.00),
			new Employee("lisi", 58, 6666.00), new Employee("wangwu", 32, 3333.00), new Employee("xueliu", 43, 2222.00),
			new Employee("tianqi", 28, 7777.00), new Employee("maer", 36, 8888.00)));

	@Test
	public void test6() {
		employees.stream().filter(e -> e.getAge() > 35).forEach(System.out::println);
		//取过滤后的前两个
		employees.stream().filter(e -> e.getAge() > 35).limit(2).forEach(System.out::println);
		//获取集合中每个员工的名字
		employees.stream().map(Employee::getName).forEach(System.out::println);
	}
}

猜你喜欢

转载自blog.csdn.net/rubulai/article/details/88721661
今日推荐