来自lambda表达式的笔记

lambda是java8的最重要的特征之一,它可以让代码变得简洁流畅。函数式编程也终于在java8中引入,虽然之前有匿名内部类。

什么是lambda?

lambda表达式是一段可以传递的代码,它的核心思想是将面向对象中的传递数据变成传递行为。

  • 不使用lambda:
1
2
3
4
5
6
Runnable r = new Runnable() {
public void () {
System.out.println("do something.");
}
}
  • 使用lambda:
1
Runnable r = () -> System.out.println("do something.");

基础语法

在lambda中我们遵循如下的表达式来编写:

1
expression = (variable) -> action

lambda表达式可以包含多个参数,例如:

1
int sum = (x, y) -> x + y;

这时候我们应该思考这段代码不是之前的x和y数字相加,而是创建了一个函数,用来计算两个操作数的和。 后面用int类型进行接收,在lambda中为我们省略去了return。

默认方法

在Java语言中,一个接口中定义的方法必须由实现类提供实现。但是当接口中加入新的API时, 实现类按照约定也要修改实现,而Java8的API对现有接口也添加了很多方法,比如List接口中添加了sort方法。 如果按照之前的做法,那么所有的实现类都要实现sort方法,JDK的编写者们一定非常抓狂。

幸运的是我们使用了Java8,这一问题将得到很好的解决,在Java8种引入新的机制,支持在接口中声明方法同时提供实现。 这令人激动不已,你有两种方式完成 1.在接口内声明静态方法 2.指定一个默认方法。

看在JDK8中上述List接口添加方法的问题是如何解决的:

1
2
3
4
5
6
7
8
9
default void sort(Comparator<? super E> c) {
Object[] a = this.toArray();
Arrays.sort(a, (Comparator) c);
ListIterator<E> i = this.listIterator();
for (Object e : a) {
i.next();
i.set((E) e);
}
}

翻阅List接口的源码,其中加入一个默认方法default void sort(Comparator<? super E> c)。 在返回值之前加入default关键字,有了这个方法我们可以直接调用sort方法进行排序。

经常看到使用Java8操作集合的时候可以直接foreach的原因也是在Iterable接口中也新增了一个默认方法:forEach , 该方法功能和 for 循环类似,但是允许 用户使用一个Lambda表达式作为循环体。

函数式接口

1. 消费型接口示例

1
2
3
4
5
6
7
public static void donation(Integer money, Consumer<Integer> consumer){
consumer.accept(money);
}
public static void main(String[] args) {
donation(1000, money -> System.out.println("好心的麦乐迪为Blade捐赠了"+money+"元")) ;
}

2.供给型接口示例

1
2
3
4
5
6
7
8
9
10
11
public static List<Integer> supply(Integer num, Supplier<Integer> supplier){
List<Integer> resultList = new ArrayList<Integer>() ;
for(int x=0;x<num;x++)
resultList.add(supplier.get());
return resultList ;
}
public static void main(String[] args) {
List<Integer> list = supply(10,() -> (int)(Math.random()*100));
list.forEach(System.out::println);
}

3. 函数型接口示例

转换字符串为Integer

1
2
3
4
5
6
7
public static Integer convert(String str, Function<String, Integer> function) {
return function.apply(str);
}
public static void main(String[] args) {
Integer value = convert("28", x -> Integer.parseInt(x));
}

####4. 断言型接口示例
筛选出只有2个字的水果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public static List<String> filter(List<String> fruit, Predicate<String> predicate){
List<String> f = new ArrayList<>();
for (String s : fruit) {
if(predicate.test(s)){
f.add(s);
}
}
return f;
}
public static void main(String[] args) {
List<String> fruit = Arrays.asList("香蕉", "哈密瓜", "榴莲", "火龙果", "水蜜桃");
List<String> newFruit = filter(fruit, (f) -> f.length() == 2);
System.out.println(newFruit);
}