Java8杂谈

Posted by boydfd on 2018-04-15 20:19:00 +0800

Recently by the same author:


大语言模型中一个调皮的EOS token

You may find interesting:


再看Lambda架构

Lambda Expressions

可以把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式

1. Lambda的特点:

  • 匿名:它不像普通方法一样有名字。
  • 函数:它除了不像方法一样属于某一个类外,其他的特性和方法是一样的。
  • 传递:Lambda表达式可以作为参数传递给方法或存储在变量中。
  • 简洁:不需要像匿名类一样写很多模板代码。

2. 为什么用Lambda?

因为用了Lambda明显代码更加清晰,简洁了

用之前:

inventory.sort(new Comparator<Apple>() {
	public int compare(Apple a1, Apple a2){
	return a1.getWeight().compareTo(a2.getWeight());
	}});

用之后:

inventory.sort((a1, a2) -> a1.getWeight().compareTo(a2.getWeight()));

3. Lambda的结构

lambda

  • 参数列表 - 这里它采用了Comparator中compare方法的参数,两个Apple。
  • 箭头 -> - 把参数列表与Lambda主体分隔开。
  • Lambda主体 - 比较两个Apple的重量。表达式的返回值就是Lambda的返回值。

4. Lambda的主要形式

(parameters) -> expression

或者:

(parameters) -> { statements; }

函数式接口

只定义一个抽象方法的接口

1. 例子

@FunctionalInterface
public interface Runnable {
	public void run();
}

Runnable r = () -> System.out.println("Hello World!");

2. Java自带的库中一些比较有用的函数式接口

  • Predicate<T> - a boolean-valued property of an object
  • Consumer<T> - an action to be performed on an object
  • Function<T,R> - a function transforming a T to a R
  • Supplier<T> - provide an instance of a T (such as a factory)
  • UnaryOperator<T> - a function from T to T
  • BinaryOperator<T> - a function from (T,T) to T

3. 函数式接口和Lambda有什么联系?

Lambda表达式允许你直接以内联的形式为函数接口的抽象方法提供实现,并把整个表达式作为函数式接口的实例。

讲人话:

当你调用的函数参数是函数式接口的时候,你可以先用Lambda来实例化一个这个接口,并作为值传入。

4. 再看一遍刚刚的例子

使用Lambda之前:

inventory.sort(new Comparator<Apple>() {
	public int compare(Apple a1, Apple a2){
	return a1.getWeight().compareTo(a2.getWeight());
	}});

使用Lambda之后:

inventory.sort((a1, a2) -> a1.getWeight().compareTo(a2.getWeight()));

方法引用

把已经存在的方法当成一个函数接口的实例

1.例子

class Person {
	private String name;
	private int age;

	public int getAge() {return this.age;}
	public String getName() {return this.name;}
}

Person[] people = ...;
Comparator<Person> byName = Comparator.comparing(Person::getName);
Arrays.sort(people, byName);

2. 方法引用的类型

  • 静态方法引用 (ClassName::staticMethod)
  • 一个实例对象的方法引用 (instanceRef::instanceMethod)
  • 只想任意类型实例方法的方法引用 (ClassName::instanceMethod)
  • 一个对象的父类方法引用 (super::instanceMethod)
  • 类的构造方法引用 (ClassName::new)
  • 数组的构造方法引用 (TypeName[]::new)

3. 方法引用对应的lambda

  • 静态方法引用 (ClassName::staticMethod)
     ClassName::staticMethod
     (args) -> ClassName.staticMethod(args)
    
  • 一个实例对象的方法引用 (instanceRef::instanceMethod)
     expr::instanceMethod
     (args) -> expr.instanceMethod(args)
    
  • 指向任意类型实例方法的方法引用 (ClassName::instanceMethod)
     ClassName::instanceMethod
     (arg0, rest) -> arg0.instanceMethod(rest)
    
     换一种思考,其实是ClassName::instanceMethod(arg0, rest)
     当然这种调用方法在Java里面是没有的
    
  • 一个父类对象的方法引用 (super::instanceMethod)
     super::instanceMethod
     (args) -> super.instanceMethod(args)
    
  • 类的构造方法引用 (ClassName::new)
     ClassName::new
     (args) -> new ClassName(args)
    
  • 数组的构造方法引用 (TypeName[]::new)
     TypeName[]::new
     () -> new TypeName[]
    

总结

Stream的内容比较多,下次再讲。

to be continue…