Java 8中新增了函数——值的一种新形式。函数做为一等值,使用方法引用 :: 语法(即“把这个方法做为值”),做为函数式值来传递。html
File[] hiddenFiles = new File(".").listFiles(new FileFilter() { public boolean accept(File file) { return file.isHidden(); } });
只要方法中有代码(方法中的可执行部分),那么用方法引用就能够传递代码。java
File[] hiddenFiles = new File(".").listFiles(File::isHidden);
除了容许(命名)函数成为一等值外,Java 8还体现了更广义的将函数做为值的思想,包括Lambda(或匿名函数)。能够把Lambda表达式理解为简洁地表示可传递的匿名函数的一种方式:它没有名称,但它有参数列表、函数主体、返回类型,可能还有一个能够抛出的异常列表。express
Lambda表达式由参数、箭头和主体组成。在函数式接口上使用Lambda表达式。app
函数式接口就是只定义一个抽象方法的接口。函数
Lambda的基本语法是this
(parameters) -> expression
或(请注意语句的花括号)lua
(parameters) -> { statements; }
下面给出了Java 8中五个有效的Lambda表达式的例子。spa
// 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克)。code
第三个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实战》