首页 > 代码库 > 《Java 8 实战》(二)—— Lamda

《Java 8 实战》(二)—— Lamda

Lamda表达式可以理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表/函数主体/返回类型,可能还有一个可以抛出的异常列表。

 

Lamda表达式由参数/箭头和主体组成

(Apple a1, Apple a2)  -> a1.getWeight().compareTo(a2.getWeight());

 

之前的代码形式:

Comparator<Apple> byWeight = new Comparator<Apple>() {
  public int compare(Apple a1, Apple a2) {

    return a1.getWeight().compareTo(a2.getWeight());

  }

}

 

Java 8 中有效的Lamda表达式:

1,  (String s) -> s.length()

  具有一个String类型的参数,并返回一个int。Lamda表达式没有return语句,因为已经隐含了return。

2,  (Apple a) -> a.getWeight() > 150

  参数为Apple类型,返回一个boolean类型。

3,  (int x, int y) -> {

    System.out.println("Result");

    System.out.println(x+y);

  }

  该Lamda表达式具有两个int类型的参数而没有返回值。Lamda表达式可以包含多行语句。

  () -> {return "Mario";}

  该Lamda表达式也是有效的。

4, () - > 42

  该Lamda表达式没有参数,返回一个int

5, (Apple a1, Apple a2) -> a1.getWeight().compareTo(a2.getWeight())

  该表达式具有两个Apple类型的参数,返回一个int

 

无效Lamda表达式

(Integer i) -> return "Alan" + i;

(String s) -> {"IronMan";}

第一个表达式中,return是一个控制流语句。要使得这个语句有效,需要加上花括号。

第二个表达式中,"IronMan" 是一个表达式,不是语句。要使得此Lamda有效,可以去除花括号和分号。

 

Lamda基本语法

(parameters) -> expression

or

(parameters) -> { statements;}

 

可以使用Lamda表达式的地方 —— 函数式接口

  函数式接口就是只定义一个抽象方法的接口。如Comparator和Runnable接口。

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

  函数式接口的抽象方法的签名就是Lamda表达式的签名。这种抽象方法叫做函数描述符。

  新的Java API中,函数式接口带有@FunctionalInterface的标注。如果用@FunctionalInterface定义了一个接口,但它却不是函数式接口的话,便一起将返回一个提示原因的错误,例如“Multiple non-overriding abstract methods found in interface Foo”,表明存在多个抽象方法。

 

使用Lamda表达式的步骤

1,行为参数化:

  提取Lamda表达式,设计好参数,函数主体和返回值。

2,使用函数式接口来传递行为:

  创建一个能匹配Lamda表达式的函数式接口I,并把这个接口作为参数传递给需要使用Lamda表达式的函数M。

3,执行函数式接口中的行为

  在函数M中调用接口I中的抽象函数

4,传递Lamda表达式

 

常用函数式接口:

Java 8 以前已有的函数式接口:

  Comparable

  Runnable

  Callable

Java 8 在java.util.function包中引入的新的函数式接口:

  Predicate  

@FunctionalInterface
public interface Predicate<T>{
    boolean test(T t);
}
public static <T> List<T> filter(List<T> list, Predicate<T> p) {
    List<T> results = new ArrayList<>();
    for(T s: list){
        if(p.test(s)){
            results.add(s);
        }
    }
    return results;
}
Predicate<String> nonEmptyStringPredicate = (String s) -> !s.isEmpty();
List<String> nonEmpty = filter(listOfStrings, nonEmptyStringPredicate);

  Consumer  

  

@FunctionalInterface
public interface Consumer<T>{
    void accept(T t);
}
public static <T> void forEach(List<T> list, Consumer<T> c){    
    for(T i: list){
        c.accept(i);
    }
}
forEach(Arrays.asList(1,2,3,4,5),(Integer i) -> System.out.println(i));

  Function

@FunctionalInterface
public interface Function<T, R>{
    R apply(T t);
}
public static <T, R> List<R> map(List<T> list,Function<T, R> f) {
    List<R> result = new ArrayList<>();
    for(T s: list){
        result.add(f.apply(s));
    }
    return result;
}

List<Integer> l = map(Arrays.asList("lambdas","in","action"),(String s) -> s.length());

 

 

Lamda及函数式接口例子

使用案例  Lambda的例子  对应的函数式接口
布尔表达式  (List<String> list) -> list.isEmpty()   Predicate<List<String>>
创建对象  () -> new Apple(10) Supplier<Apple>
消费一个对象 (Apple a) -> System.out.println(a.getWeight())

 
     
     
     

 

       Lambda的例子                   对应的函数式接口

                     
 
消费一个对象 (Apple a) ->
System.out.println(a.getWeight())
Consumer<Apple>
从一个对象中
选择/提取
(String s) -> s.length() Function<String, Integer>或
ToIntFunction<String>
合并两个值 (int a, int b) -> a * b IntBinaryOperator
比较两个对象 (Apple a1, Apple a2) ->
a1.getWeight().compareTo(a2.getWeight())
Comparator<Apple>或
BiFunction<Apple, Apple, Integer>
或ToIntBiFunction<Apple, Apple>

《Java 8 实战》(二)—— Lamda