Post

Java 8的Lambda表达式

啥是Lambda表达式?写个最简单的看看:

1
2
3
4
5
6
7
8
9
Runnable runnable1 = new Runnable() {	
	@Override
	public void run() {
		System.out.println("runnable1 start!!!");
	}
};
Runnable runnable2 = () -> System.out.println("runnable2 start!!!");
runnable1.run();
runnable2.run();

这个是一个无参数无返回值的例子,可以直接写成()->expression

1
2
3
4
5
6
7
8
9
JButton testButton = new JButton("Test Button");
testButton.addActionListener(new ActionListener() {
	@Override
	public void actionPerformed(ActionEvent ae) {
		System.out.println("Click Detected by Anon Class");
	}
});
testButton.addActionListener(e -> System.out
		.println("Click Detected by Lambda Listner"));

这个是一个有参数无返回值的例子,可以直接写成e->expression

1
2
3
4
5
6
7
8
9
List<Person> personList = Person.createShortList();
// Sort with Inner Class
Collections.sort(personList, new Comparator<Person>(){
  public int compare(Person p1, Person p2){
    return p1.getSurName().compareTo(p2.getSurName());
  }
});
// Use Lambda instead
Collections.sort(personList, (Person p1, Person p2) -> p1.getSurName().compareTo(p2.getSurName()));

这个是一个有参数有返回值的例子,可以直接写成(p1,p2)->{return expression;} 当你看到这里,你虽然不明白为什么,但是你确实是会使用了最基本的几种Predicate Lambda表达式的用法,我们先不管Lambda的优劣,只是研究一下它的特点.如果你自己定义了一个接口你可以使用@FunctionalInterface来声明,但是不管声明不声明,java 8都会默认看做是函数式接口

Java 8 提供了多种类型的function

  • Predicate: A property of the object passed as argument
  • Consumer: An action to be performed with the object passed as argument
  • Function: Transform a T to a U
  • Supplier: Provide an instance of a T (such as a factory)
  • UnaryOperator: A unary operator from T -> T
  • BinaryOperator: A binary operator from (T, T) -> T

如果是集合,遍历的时候可以选择使用forEach

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
List<Person> pl = Person.createShortList();
pl.forEach( p -> p.printWesternName() );
pl.forEach(Person::printEasternName);
pl.forEach(p -> { System.out.println(p.printCustom(r -> "Name: " + r.getGivenName())); });
pl.stream().filter(p->p.getAge()>16)
  .forEach(Person::printWesternName);

// Make a new list after filtering.
Predicate<Person> allDraftees = p -> p.getAge() >= 18 && p.getAge() <= 25 && p.getGender() == Gender.MALE;
List<Person> pilotList = pl
        .stream()
        .filter(allDraftees)
        .collect(Collectors.toList());

Predicate<Person> allPilots = p -> p.getAge() >= 23 && p.getAge() <= 65;
long totalAge = pl
        .stream()
        .filter(allPilots)
        .mapToInt(p -> p.getAge())
        .sum();

// Get average of ages
OptionalDouble averageAge = pl
        .parallelStream()
        .filter(allPilots)
        .mapToDouble(p -> p.getAge())
        .average();

接下来的混合使用,我没弄太明白,这种扩展了很多层的,看起来就头晕啊…

1
2
3
4
5
6
7
8
9
10
11
12
public static <X, Y> void processElements(
    Iterable<X> source,
    Predicate<X> tester,
    Function <X, Y> mapper,
    Consumer<Y> block) {
    for (X p : source) {
        if (tester.test(p)) {
            Y data = mapper.apply(p);
            block.accept(data);
        }
    }
}

参考
Lambda-QuickStart
LambdaExpressions
LambdaExpressions性能影响

This post is licensed under CC BY 4.0 by the author.