首页 > 技术文章 > JDK_8新特性_Lambda表达式

Small-music 2018-08-16 10:23 原文

Lambda 表达式基础语法

  Lambda 表达式的基础语法:
Java8中引入了一个新的操作符 "->" 该操作符称为箭头操作符或 Lambda 操作符 箭头操作符将 Lambda 表达式拆分成两部分: 左侧:Lambda 表达式的参数列表 右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体 语法格式一:无参数,无返回值 () -> System.out.println("Hello Lambda!"); 语法格式二:有一个参数,并且无返回值 (x) -> System.out.println(x) 语法格式三:若只有一个参数,小括号可以省略不写 x -> System.out.println(x) 语法格式四:有两个以上的参数,有返回值,并且 Lambda 体中有多条语句 Comparator<Integer> com = (x, y) -> { System.out.println("函数式接口"); return Integer.compare(x, y); }; 语法格式五:若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写 Comparator<Integer> com = (x, y) -> Integer.compare(x, y); 语法格式六:Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断” Comparator<Integer> com = (Integer x, Integer y) -> Integer.compare(x, y);

 

Lambda 表达式演变

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.junit.Test;

public class TestLambda1 {

	private List<Apple> apples = Arrays.asList(new Apple(80,"green"), new Apple(155, "green"), new Apple(120, "red"));


	/**
	 * 优化方式四:Stream API
	 */
	@Test
	public void Test4() {
		apples.stream()
			  .filter((a) -> a.getWeight() > 150)
			  .forEach(System.out::println);
	}

	/**
	 * 优化方式三:Lambda 表达式
	 */
	@Test
	public void Test3() {
		List<Apple> list1 = filterApples(apples, (Apple a) -> "green".equals(a.getColor()));
		list1.forEach(System.out::println);
		
		System.out.println("------------------------------------------");
		
		List<Apple> list2 = filterApples(apples, (Apple a) -> a.getWeight() > 150);
		list2.forEach(System.out::println);
	}

	/**
	 * 优化方式二:匿名内部类
	 */
	@Test
	public void Test2() {
		List<Apple> list = filterApples(apples, new ApplePredicate() {
			public boolean test(Apple apple){
				return "green".equals(apple.getColor());
			}
		});
		for (Apple apple : list) {
			System.out.println(apple);
		}
	}

	/**
	 * 优化方式一:策略设计模式
	 */
	@Test
	public void Test1() {
		List<Apple> list1 = filterApples(apples, new GreenApplePredicate()); 
		for (Apple apple : list1) {
			System.out.println(apple);
		}
		
		System.out.println("------------------------------------------");
		
		List<Apple> list2 = filterApples(apples, new HeavyApplePredicate()); 
		for (Apple apple : list2) {
			System.out.println(apple);
		}
	}


	public List<Apple> filterApples(List<Apple> apples, ApplePredicate p){
		List<Apple> result = new ArrayList<>();
		for(Apple apple : apples){
			if(p.test(apple)){
				result.add(apple);
			}
		}
		return result;
	} 

	@FunctionalInterface
	public interface ApplePredicate{
		public boolean test(Apple a);
	}
	public class GreenApplePredicate implements ApplePredicate{
		public boolean test(Apple apple){
			return "green".equals(apple.getColor());
		}
	}
	public class HeavyApplePredicate implements ApplePredicate{
		public boolean test(Apple apple){
			return apple.getWeight() > 150;
		}
	}
	
	/**
	 * 需求2:筛选超过150克的苹果
	 * @param inventory
	 * @return
	 */
	public List<Apple> filterHeavyApples(List<Apple> inventory){
		List<Apple> result = new ArrayList<>();
		for (Apple apple: inventory){
			if (apple.getWeight() > 150) {
				result.add(apple);
			}
		}
		return result;
	} 

	/**
	 * 需求1:筛选绿色苹果
	 * @param inventory
	 * @return
	 */
	public List<Apple> filterGreenApples(List<Apple> inventory){
		List<Apple> result = new ArrayList<>();
		for (Apple apple: inventory){
			if ("green".equals(apple.getColor())) {
				result.add(apple);
			}
		}
		return result;
	}

	/**
	 * Apple实体类
	 */
	public class Apple {
		private int weight = 0;
		private String color = "";

		public Apple(int weight, String color){
			this.weight = weight;
			this.color = color;
		}

		public Integer getWeight() {
			return weight;
		}

		public void setWeight(Integer weight) {
			this.weight = weight;
		}

		public String getColor() {
			return color;
		}

		public void setColor(String color) {
			this.color = color;
		}

		public String toString() {
			return "Apple{" + "color='" + color + '\'' + ", weight=" + weight + '}';
		}
	}
}

 

Lambda 表达式需要“函数式接口”的支持

自定义函数式接口

import org.junit.Test;

public class TestLambda2 {
	
	/**
	 * 需求:对一个数进行运算
	 */
	@Test
	public void test(){
		System.out.println(operation(100, (x) -> x * x));
		System.out.println(operation(200, (y) -> y + 200));
	}
	
	public Integer operation(Integer num, MyFun fun){
		return fun.getValue(num);
	}
	
	/**
	 * 自定义接口函数
	 * 
	 * @FunctionalInterface:该注解用于编译器校验该函数接口是否合法即用于限制一个接口中只有一个抽象方法方法
	 */
	@FunctionalInterface
	public interface MyFun{
		public Integer getValue(Integer num);
	}
	
}

内置四大核心函数式接口

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.function.Supplier;

import org.junit.Test;

/**
 * Java8 内置的四大核心函数式接口
 * 
 * Consumer<T> : 消费型接口
 * 		void accept(T t);
 * 
 * Supplier<T> : 供给型接口
 * 		T get(); 
 * 
 * Function<T, R> : 函数型接口
 * 		R apply(T t);
 * 
 * Predicate<T> : 断言型接口
 * 		boolean test(T t);
 * 
 */
public class TestLambda3 {

	/**
	 * Consumer<T> 消费型接口
	 */
	@Test
	public void test1(){
		print("Hello World!", (s) -> System.out.println(s));
	}

	// 需求:打印传入的内容信息
	public void print(String str, Consumer<String> con){
		con.accept(str);
	}

	
	/**
	 * Supplier<T> 供给型接口
	 */
	@Test
	public void test2(){
		List<Integer> list = supplier(10, () -> (int)(Math.random() * 100));

		for (Integer i : list) {
			System.out.println(i);
		}
	}
	
	// 需求:产生指定个数的整数,并放入集合中
    public List<Integer> supplier(int len, Supplier<Integer> sup){
        List<Integer> list = new ArrayList<Integer>();
        for (int i = 0; i < len; i++) {
            list.add(sup.get());
        }
        return list;
    }
	

	/**
	 * Function<T, R> 函数型接口
	 */
	@Test
	public void test3(){
        String str = strHandler("abcdef", (s) -> s.toUpperCase());
        System.out.println(str);
	}
	
	// 需求:用于处理字符串
    public String strHandler(String str, Function<String, String> fun) {
        return fun.apply(str);
    }

    
	/**
	 * Predicate<T> 断言型接口
	 */
	@Test
	public void test4(){
	    List<String> list = Arrays.asList("hello", "world", "Lambda", "www", "ok");
	    List<String> strList = filterStr(list, (s) -> s.length() > 3);
	    for (String str :strList) {
	        System.out.println(str);
	    }
	}
	
	// 需求:将满足条件的值,放入集合中
	public List<String> filterStr(List<String> list, Predicate<String> predicate) {
	    List<String> strlist = new ArrayList<>();
	    for (String str : list) {
	        if (predicate.test(str)) {
	            strlist.add(str);
	        }
	    }
	    return strlist;
	}

}

常用函数式接口

 

方法引用

import java.util.Comparator;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Function;
import java.util.function.Supplier;

import org.junit.Test;

/**
 * 一、方法引用:若 Lambda 体中的功能,已经有方法提供了实现,可以使用方法引用
 * 			  (可以将方法引用理解为 Lambda 表达式的另外一种表现形式)
 * 
 *  对象的引用 :: 实例方法名
 *  类名 :: 静态方法名
 *  类名 :: 实例方法名
 * 
 * 注意:
 * 	 1. 方法引用所引用的方法的参数列表与返回值类型,需要与函数式接口中抽象方法的参数列表和返回值类型保持一致!
 * 	 2. 若Lambda 的参数列表的第一个参数,是实例方法的调用者,第二个参数(或无参)是实例方法的参数时,格式: ClassName::MethodName
 * 
 * 二、构造器引用 :构造器的参数列表,需要与函数式接口中参数列表保持一致!
 *  类名 :: new
 * 
 * 三、数组引用
 * 	类型[] :: new
 * 
 */
public class TestLambda4 {
	
	/**
	 * 数组引用
	 */
	@Test
	public void test5(){
		Function<Integer, String[]> fun1 = (args) -> new String[args];
		String[] strs1 = fun1.apply(10);
		System.out.println(strs1.length);
		
		System.out.println("--------------------------");
		
		Function<Integer, String[]> fun2 = String[] :: new;
		String[] strs2 = fun2.apply(20);
		System.out.println(strs2.length);
	}
	
	/**
	 * 构造器引用
	 */
	@Test
	public void test4(){
		Supplier<Apple> sup1 = () -> new Apple();
		System.out.println(sup1.get());
		
		System.out.println("------------------------------------");
		
		Supplier<Apple> sup2 = Apple::new;
		System.out.println(sup2.get());
		
		System.out.println("------------------------------------");
		
		Function<Integer, Apple> fun = Apple::new;
		System.out.println(fun.apply(100));
		
		System.out.println("------------------------------------");
		
		BiFunction<Integer, String, Apple> bfun = Apple::new;
		System.out.println(bfun.apply(90, "red"));
	}
	
	/**
	 * 类名 :: 实例方法名
	 */
	@Test
	public void test3(){
		BiPredicate<String, String> bp1 = (x, y) -> x.equals(y);
		System.out.println(bp1.test("abcde", "abcde"));
		
		System.out.println("-----------------------------------------");
		
		BiPredicate<String, String> bp2 = String::equals;
		System.out.println(bp2.test("abc", "abcd"));
		
		System.out.println("-----------------------------------------");
		
		Function<Apple, String> fun1 = (e) -> e.show();
		System.out.println(fun1.apply(new Apple()));
		
		System.out.println("-----------------------------------------");
		
		Function<Apple, String> fun2 = Apple::show;
		System.out.println(fun2.apply(new Apple()));
		
	}
	
	/**
	 * 类名 :: 静态方法名
	 */
	@Test
	public void test2(){
		Comparator<Integer> com1 = (x, y) -> Integer.compare(x, y);
		
		System.out.println("-------------------------------------");
		
		Comparator<Integer> com2 = Integer::compare;
	}
	
	/**
	 * 对象的引用 :: 实例方法名
	 */
	@Test
	public void test1(){
		Apple apple = new Apple(80,"green");
		
		Supplier<String> sup1 = () -> apple.getColor();
		System.out.println(sup1.get());
		
		System.out.println("----------------------------------");
		
		Supplier<String> sup2 = apple::getColor;
		System.out.println(sup2.get());
	}
	
	/**
	 * Apple实体类
	 */
	public class Apple {
		private int weight = 0;
		private String color = "";

		public Apple(){}
		
		public Apple(int weight){
			this.weight = weight;
		}
		
		public Apple(int weight, String color){
			this.weight = weight;
			this.color = color;
		}

		public Integer getWeight() {
			return weight;
		}

		public void setWeight(Integer weight) {
			this.weight = weight;
		}

		public String getColor() {
			return color;
		}

		public void setColor(String color) {
			this.color = color;
		}

		public String toString() {
			return "Apple{" + "color='" + color + '\'' + ", weight=" + weight + '}';
		}
		
		public String show() {
			return "测试方法引用!";
		}
	}
	
}

 

推荐阅读