Java 8的核心新特性:Lambda(匿名函数)、流、默认方法

Java 中的函数

Java 8中新增了函数——值的一种新形式。函数作为一等值,使用方法引用 :: 语法(即“把这个方法作为值”),作为函数式值来传递。

File[] hiddenFiles = new File(".").listFiles(new FileFilter() {
    public boolean accept(File file) {
         return file.isHidden();
    }
});

只要方法中有代码(方法中的可执行部分),那么用方法引用就可以传递代码。

File[] hiddenFiles = new File(".").listFiles(File::isHidden);

Lambda——匿名函数

除了允许(命名)函数成为一等值外,Java 8还体现了更广义的将函数作为值的思想,包括Lambda(或匿名函数)。可以把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个可以抛出的异常列表。

Lambda表达式由参数、箭头和主体组成。在函数式接口上使用Lambda表达式。

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

Lambda的基本语法是

(parameters) -> expression

或(请注意语句的花括号)

(parameters) -> { statements; }

下面给出了Java 8中五个有效的Lambda表达式的例子。

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

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

// 3
(int x, int y) -> {
   System.out.println("Result:");
   System.out.println(x+y);
}

// 4
() -> 42

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

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

第二个Lambda表达式有一个Apple 类 型 的参数并返回一个 boolean (苹果的重量是否超过150克)。

第三个Lambda表达式具有两个 int 类型的参数而没有返回值( void 返回)。注意Lambda表达式可以包含多行语句,这里是两行。

第四个Lambda表达式没有参数,返回一个int 。

第五个Lambda表达式具有两个 Apple 类型的参数,返回一个 int :比较两个 Apple 的重量。

和Collection API相比,Stream API处理数据的方式非常不同。用集合的话,你得自己去做迭代的过程。你得用 for-each 循环一个个去迭代元素,然后再处理元素。我们把这种数据迭代的方法称为外部迭代。相反,有了Stream API,你根本用不着操心循环的事情。数据处理完全是在库内部进行的。我们把这种思想叫作内部迭代

Collection主要是为了存储和访问数据,而Stream则主要用于描述对数据的计算。这里的关键点在于,Stream允许并提倡并行处理一个 Stream 中的元素。虽然可能乍看上去有点儿怪,但筛选一个 Collection 的最快方法常常是将其转换为 Stream ,进行并行处理,然后再转换回 List 。 

比如,利用Stream和Lambda表达式顺序或并行地从一个列表里筛选比较重的苹果。

import static java.util.stream.Collectors.toList;

List<Apple> inventory = Arrays.asList(new Apple(80,"green"),
                                      new Apple(155, "green"),
                                      new Apple(120, "red"));	

List<Apple> apples = inventory.stream()
                .filter((Apple a) -> a.getWeight() > 150)
                .collect(toList());

// 并行处理
List<Apple> apples2 = inventory.parallelStream()
                .filter((Apple a) -> a.getWeight() > 150)
                .collect(toList());

filter方法传入的参数其实是谓词,我们来看下JDK8 Predicate类源码。

package java.util.function;

import java.util.Objects;

/**
 * Represents a predicate (boolean-valued function) of one argument.
 *
 * <p>This is a <a href="package-summary.html">functional interface</a>
 * whose functional method is {@link #test(Object)}.
 *
 * @param <T> the type of the input to the predicate
 *
 * @since 1.8
 */
@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);

    // ...
}
什么是谓词?

谓词(predicate)在数学上常常用来代表一个类似函数的东西,它接受一个参数值,并返回 true 或 false 。

filter通过行为参数化进行代码传递。行为参数化,就是一个方法接受多个不同的行为作为参数,并在内部使用它们,完成不同行为的能力。其实就是策略模式,它可以把一个行为(一段代码)封装起来,并通过传递和使用创建的行为(例如不同谓词)将方法的行为参数化。行为参数化可以让代码更好地适应不断变化的要求,减轻未来的工作量。

Java API中的很多方法都可以用不同的行为来参数化(比如Comparator 排序,用 Runnable 执行一个代码块,以及GUI事件处理),这些方法往往与匿名类一起使用。

默认方法

Java 8中加入默认方法主要是为了支持库设计师,让他们能够写出更容易改进的接口。在接口中使用默认方法,在实现类没有实现方法时提供方法内容。在接口声明中使用新的 default 关键字来表示这一点。

参考

书籍《Java 8实战》

转载于:https://my.oschina.net/lienson/blog/3052145

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值