Java8 学习笔记(一) —— Lambda 表达式 与 函数式接口

先来一段传统的匿名内部类调用程序

//定义一个数学接口
public interface Maths {
	//定义一个计算的接口方法
	int calc(int a, int b);
}
//测试类
public class MathsTester {
	
	//定义一个打印计算结果的方法
	public static void printCalcResult(int a,int b,Maths maths){
		System.out.println(maths.calc(a, b));
	}

}
//传统的匿名内部类使用方法
public static void main(String[] args) {

	//定义两个数
	int a = 10;
	int b = 5;

	//两个数相加;
	MathsTester.printCalcResult(a, b, new Maths() {
		@Override
		public int calc(int a, int b) {
			return a + b;
		}
	});

	//两个数相减;
	MathsTester.printCalcResult(a, b, new Maths() {
		@Override
		public int calc(int a, int b) {
			return a * b;
		}
	});
}

使用Lambda表达式后

public static void main(String[] args) {
	
	//定义两个数
	int a = 10;
	int b = 5;
	
	//使用lambda表达式定义4个接口的实现类,(num1, num2):括号中的参数不能与外面的变量a和b重名
	Maths add = (num1, num2) -> num1 + num2;  //加
	Maths sub = (num1, num2) -> num1 + num2;  //减
	
	//打印计算结果
	MathsTester.printCalcResult(a, b, add);
	MathsTester.printCalcResult(a, b, sub);

	//简单的写法
	MathsTester.printCalcResult(a, b, (num1, num2) -> num1 * num2);
	MathsTester.printCalcResult(a, b, (num1, num2) -> num1 / num2);
	
	//先判断,在选择如何计算,有多行语句时,要使用花括号{}
	MathsTester.printCalcResult(a, b, (num1, num2) -> {
		if (num1 > num2) {
			return num1 - num2;
		} else {
			return num1 + num2;
		}
	});

	//直接调用接口方法
	System.out.println(add.calc(a, b));
	System.out.println(add.calc(a, b));
	
	//无参数lambda表达式:() -> xxx
	
	//仅当接口的方法有且仅有一个抽象方法时,才能使用lambda表达式
}

函数式接口

函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。函数式接口可以被隐式转换为 lambda 表达式

//使用注解定义该接口是一个函数式接口,也可以不加注解,只要遵循函数式接口的定义就可以 了,使用注解java编译器会自动识别错误
@FunctionalInterface
public interface Hello {
	
	//抽象方法有且只有一个
	void hello();
	
	//默认方法,jdk8以前是不允许在接口中的方法有方法体的,可以定义多个默认方法
	default void hi(){
		System.out.println("hi..........");
	}
	
	default void o(){
		System.out.println("o...........");
	}
	
	//可以定义静态方法
	static void he(){
		System.out.println("he..........");
	}
}
//接口实现类
public class HelloImpl implements Hello {

	//接口抽象方法实现
	@Override
	public void hello() {
		// TODO Auto-generated method stub
		
	}

	//可以重写父接口的默认方法,也可以不重写,Hello.o()方法,我们就没重写
	@Override
	public void hi() {
		Hello.super.hi(); //调用父接口的实现
		System.out.println("..........hi");
	}
	
	public static void main(String[] args) {
		
		//常规接口实例化
		Hello hello = new HelloImpl(); 
		hello.hi();
		
		//lambda表达式实例化接口
		Hello _hello = () -> System.out.println("ho......");
		_hello.hello();
		_hello.o();
		
		//调用父接口的静态方法
		Hello.he();  
		
	}
}

内置的函数式接口

java.util.function 包下含了很多函数式接口,这里我们主要讲解四个核心接口,其他接口依葫画瓢

@FunctionalInterface
public interface Consumer {
    void accept(T t); //表示接受单个输入参数并且不返回结果的操作
    ......
}
@FunctionalInterface
public interface Supplier {
    T get();  //获得结果
}
@FunctionalInterface
public interface Function {
    R apply(T t);  //输入一个参数,返回一个结果R
    ......
}
@FunctionalInterface
public interface Predicate {
    boolean test(T t); //输入一个参数,返回布尔值
    ......
}
public class Tester {

	//Consumer
	public void happy(double money, Consumer consumer){
		consumer.accept(money);
	}
	
	@Test
	public void testHappy(){
		happy(1000, (m) -> System.out.println("这次去happy,一共消费了"+m+"元"));
	}
	
	//Supplier
	public List fillList(int size,Supplier supplier){
		List list = new ArrayList();
		for (int i = 0; i < size; i++) {
			list.add(supplier.get());
		}
		return list;
	}
	
	@Test
	public void testFillList(){
		System.out.println(fillList(10, () -> Math.random() + ""));
	}
	
	//Function
	public String strHandler(String str, Function fun){
		return fun.apply(str);
	}
	
	@Test
	public void testStrHandler(){
		System.out.println(strHandler("\t\t\t清除两端空格    ", (str) -> str.trim()));
	}
	
	//Predicate
	public List filterStr(List list, Predicate pre){
		List newList = new ArrayList<>();
		for (int i = 0; i < list.size(); i++) {
			if(pre.test(list.get(i))){
				newList.add(list.get(i));
			}
		}
		return newList;
	}
	
	@Test
	public void testFilterStr(){
		List list = new ArrayList<>(Arrays.asList("Hello", "atguigu", "Lambda", "www", "ok"));
		System.out.println(filterStr(list, (s) -> s.length() > 3));
	}
}

其他函数式接口描述:https://www.runoob.com/java/java8-functional-interfaces.html

方法引用

方法引用比lambda表达式代码量更简洁

public static void main(String[] args) {
	
	//lambda表达式的写法
	Consumer consumer = (str) -> System.out.println(str); 
	//方法引用的写法,使用两个英文冒号,后面跟方法名
	//要求println方法的入参和返回值和Consumer接口的方法一直才能这样使用
	Consumer _consumer = System.out::println; 
	
	//其他示例
	Supplier supplier = () -> Math.random();
	Supplier _supplier = Math::random;  //使用静态方法
	
	//使用第一个参数的方法进行调用
	BiPredicate bp = (x, y) -> x.equals(y);
	BiPredicate bp2 = String::equals;
	System.out.println(bp.test("abcde", "abcde"));
	
	//比较两个Employee类
	BiPredicate biPredicate = (e1,e2) -> e1.compare(e2);
	//第一个入参是e1,返回值时使用e1.compare返回的,这种情况就可以简写为e1::xxx
	BiPredicate bp3 = Employee::compare; 
	System.out.println(bp3.test(new Employee("zhangsan"), new Employee("lisi")));
	
	//构造方法引用
	Supplier supplier3 = Employee::new;
	Employee employee = supplier3.get();
	
	//有参构造方法引用
	Function function = Employee::new;
	Employee employee2 = function.apply("wangwu");

	//数组引用
	Function fun = (size) -> new String[size];
	Function fun2 = Employee[] :: new;
}

public class Employee {

	private int id;
	private String name;
	private int age;
	private double salary;

	public Employee() { }

	public Employee(String name) {
		this.name = name;
	}
	
	public boolean compare(Employee employee){
		return this.getName().equals(employee.getName());
	}

}

 

你可能感兴趣的:(java8)