电源 东莞网站建设,公司建网站多少钱晋江文学城,seo排名优化的网站,设计企业网站步骤利用行为参数化来传递代码有助于应对不断变化的需求。它允许你定义一段代码块来表示一个行为#xff0c;然后传递它。采用匿名类来表示多种行为并不令人满意#xff1a;代码十分啰唆#xff0c;这会影响程序员在实践中使用行为参数化的积极性。
3.1 Lambda 管中窥豹
可以…利用行为参数化来传递代码有助于应对不断变化的需求。它允许你定义一段代码块来表示一个行为然后传递它。采用匿名类来表示多种行为并不令人满意代码十分啰唆这会影响程序员在实践中使用行为参数化的积极性。
3.1 Lambda 管中窥豹
可以把 Lambda 表达式理解为一种简洁的可传递匿名函数它没有名称但它有参数列表、函数主体、返回类型可能还有一个可以抛出的异常列表。这个定义够大的让我们慢慢道来。
匿名——说它是匿名的因为它不像普通的方法那样有一个明确的名称写得少而想得多函数——说它是一种函数是因为 Lambda 函数不像方法那样属于某个特定的类。但和方法一样Lambda 有参数列表、函数主体、返回类型还可能有可以抛出的异常列表。传递——Lambda 表达式可以作为参数传递给方法或存储在变量中。简洁——你无须像匿名类那样写很多模板代码。
Lambda 解决了这个问题它可以让你十分简明地传递代码。理论上来说你在 Java 8 之前做不了的事情Lambda 也做不了.利用 Lambda 表达式你可以更为简洁地自定义一个 Comparator 对象。
之前
ComparatorApple byWeight new ComparatorApple() { public int compare(Apple a1, Apple a2){ return a1.getWeight().compareTo(a2.getWeight()); }
}; 现在 lambda方式
ComparatorApple byWeight (Apple a1, Apple a2) - a1.getWeight().compareTo(a2.getWeight()); lambda有三个部分
参数列表——这里它采用了 Comparator 中 compare 方法的参数两个 Apple。箭头——箭头 - 把参数列表与 Lambda 主体分隔开。Lambda 主体——比较两个 Apple 的重量。表达式就是 Lambda 的返回值。
例子
Lambda 表达式具有一个 String 类型的参数并返回一个 int。Lambda 没有 return 语句因为已经隐含了 return
(String s) - s.length() Lambda表达式有一个Apple类型的参数并返回一个 boolean苹果的重量是否超过 150 克
(Apple a) - a.getWeight() 150Lambda 表达式具有两个 int 类型的参数而没有返回值void返回。注意 Lambda 表达式可以包含多行语句这里是两行
(int x, int y) - { System.out.println(Result:); System.out.println(x y);
} Lambda 表达式没有参数返回一个 int
() - 42 Lambda表达式具有两个 Apple 类型的参数返回一个 int比较两个 Apple 的重量
(Apple a1, Apple a2) - a1.getWeight().compareTo(a2.getWeight()) 基本语法
(parameters) - expression
块风格
(parameters) - { statements; } 测验 3.1Lambda 语法 以下哪个不是有效的 Lambda 表达式 (1) () - {} (2) () - “Raoul” (3) () - {return “Mario”;} (4) (Integer i) - return “Alan” i; (5) (String s) - {“Iron Man”;} 答案只有(4)和(5)是无效的 Lambda其余都是有效的。详细解释如下。 (1) 这个 Lambda 没有参数并返回 void。它类似于主体为空的方法public void run() {}。一个有趣的事实这种 Lambda 也经常被叫作“汉堡型 Lambda”。 如果只从一边看它的形状就像是两块圆面包组成的汉堡。 (2) 这个 Lambda 没有参数并返回 String 作为表达式。 (3) 这个 Lambda 没有参数并返回 String利用显式返回语句。 (4) return 是一个控制流语句。要使此 Lambda 有效需要使用花括号如下所示(Integer i) - {return “Alan” i;} (5)“Iron Man”是一个表达式不是一个语句。要使此 Lambda 有效可以去除花括号和 分号如下所示 (String s) - “Iron Man” 或者如果你喜欢可以使用显式返回语句如下所示 (String s) - {return “Iron Man”;} 3.2 在哪里以及如何使用 Lambda
可以在函数式接口上使用 Lambda 表达式。但是方法参数需要是这个Predicate类型的
3.2.1 函数式接口
Predicate 它就是一个函数式接口函数式接口就是只定义一个抽象方法的接口。 Java API 中的一些其他函数式接口 下面哪些接口是函数式接口 public interface Adder { int add(int a, int b); } public interface SmartAdder extends Adder { int add(double a, double b); } public interface Nothing { } 答案只有 Adder 是函数式接口。 SmartAdder 不是函数式接口因为它定义了两个叫作 add 的抽象方法其中一个是从Adder 那里继承来的。 Nothing 也不是函数式接口因为它没有声明抽象方法 用函数式接口可以干什么呢Lambda 表达式允许你直接以内联的形式为函数式接口的抽象方法提供实现并把整个表达式作为函数式接口的实例具体说来是函数式接口一个具体实现的实例
3.2.2 函数描述符
函数式接口的抽象方法的签名基本上就是 Lambda 表达式的签名。我们将这种抽象方法叫作函数描述符。Runnable 接口可以看作一个什么也不接受什么也不返回void的函数的签名因为它只有一个叫作 run 的抽象方法这个方法什么也不接受什么也不返回void。 Lambda 及空方法调用 虽然下面这种 Lambda 表达式调用看起来很奇怪但是合法的 process(() - System.out.println(“This is awesome”)); System.out.println 返回 void所以很明显这不是一个表达式为什么不像下面这样用花括号环绕方法体呢 process(() - { System.out.println(“This is awesome”); }); 结果表明方法调用的返回值为空时Java 语言规范有一条特殊的规定。这种情况下你不需要使用括号环绕返回值为空的单行方法调用。 以下哪些是使用 Lambda 表达式的有效方式 (1) execute(() - {}); public void execute(Runnable r){ r.run(); } (2) public Callable fetch() { return () - “Tricky example ”; } (3) Predicate p (Apple a) - a.getWeight(); 答案只有(1)和(2)是有效的。 第(1)个例子有效是因为 Lambda() - {}具有签名() - void这和 Runnable 中的抽象方法 run 的签名相匹配。请注意此代码运行后什么都不会做因为 Lambda 是空的 第(2)个例子也是有效的。事实上fetch 方法的返回类型是 Callable。Callable基本上就定义了一个方法签名是() - String其中 T 被 String代替了。因为 Lambda() - Trickyexample;-)的签名是() - String所以在这个上下文中可以使用 Lambda。 第(3)个例子无效因为 Lambda 表达式(Apple a) - a.getWeight()的签名是(Apple) - Integer这和 Predicate: (Apple) - boolean 中定义的 test 方法的签名不同。 3.3 把 Lambda 付诸实践环绕执行模式
在进行文件读取的时候基本上就是 打开-处理-关闭 这几个模式。大多情况下 打开和关闭都是类似的操作所以我们把这两个抽取出来在以下代码中加粗显示的就是从一个文件中读取一行所需的模板代码
3.3.1 第 1 步记得行为参数化
但是这段代码的是有局限的如果我想读取两行或者是拼接的返回那我我可能需要重写一个方法也是复制在修改一下。那么我们是不是可以把processFile方法的行为参数化呢如果想读取两行写法可以是这样的String result processFile((BufferedReader br) - br.readLine() br.readLine());
3.3.2 第 2 步使用函数式接口来传递行为
Lambda 仅可用于上下文是函数式接口的情况。你需要创建一个能匹配BufferedReader - String还可以抛出 IOException 异常的接口
FunctionalInterface
public interface BufferedReaderProcessor { String process(BufferedReader b) throws IOException;
}processFile 方法的参数public String processFile(BufferedReaderProcessor p) throws IOException {}
3.3.3 第 3 步执行一个行为
任何 BufferedReader - String 形式的 Lambda 都可以作为参数来传递因为它们符合BufferedReaderProcessor 接口中定义的 process 方法的签名。Lambda 表达式允许你直接内联为函数式接口的抽象方法提供实现并且将整个表达式作为函数式接口的一个实例。
public String processFile(BufferedReaderProcessor p) throws IOException { try (BufferedReader br new BufferedReader(new FileReader(data.txt))) { // 处理 BufferedReader 对象return p.process(br);}
} 3.3.4 第 4 步传递 Lambda
现在通过传递Lambda 来重用 processFile 方法。
处理一行
String oneLine processFile((BufferedReader br) - br.readLine());
处理两行
String twoLines processFile((BufferedReader br) - br.readLine() br.readLine()); 总结了所采取的使 pocessFile 方法更灵活的四个步骤
3.4 使用函数式接口
函数式接口定义且只定义了一个抽象方法。函数式接口很有用因为抽象方法的签名可以描述 Lambda 表达式的签名。函数式接口的抽象方法的签名称为函数描述符。
3.4.1 Predicate
java.util.function.Predicate接口定义了一个名叫 test 的抽象方法它接受泛型 T 对象并返回一个 boolean
FunctionalInterface
public interface PredicateT { boolean test(T t);
}
public T ListT filter(ListT list, PredicateT p) { ListT results new ArrayList(); for(T t: list) { if(p.test(t)) { results.add(t); } } return results;
}
PredicateString nonEmptyStringPredicate (String s) - !s.isEmpty();
ListString nonEmpty filter(listOfStrings, nonEmptyStringPredicate); 3.4.2 Consumer
java.util.function.Consumer接口定义了一个名叫 accept 的抽象方法它接受泛型 T 的对象没有返回void。你如果需要访问类型 T 的对象并对其执行某些操作就可以使用这个接口。
FunctionalInterface
public interface ConsumerT{ void accept(T t);
}
public T void forEach(ListT list, ConsumerT c){ for(T i: list){ c.accept(i); }
}
forEach( Arrays.asList(1,2,3,4,5), (Integer i) - System.out.println(i) // Lambda 是 Consumer中 accept 方法的实现); 3.4.3 Function
java.util.function.FunctionT, R接口定义了一个叫作 apply 的抽象方法它接受泛型 T 的对象并返回一个泛型 R 的对象。
FunctionalInterface
public interface FunctionT, R { R apply(T t);
}
public T, R ListR map(ListT list, FunctionT, R f) { ListR result new ArrayList(); for(T t: list) { result.add(f.apply(t)); } return result;
}
// [7, 2, 6]
ListInteger l map( Arrays.asList(lambdas, in, action), (String s) - s.length()); //Lambda是Function接口的 apply 方法的实现Java 类型要么是引用类型要么是基本类型但是泛型比如 Consumer中的 T只能绑定到引用类型。这是由泛型内部的实现方式造成的。把基本类型转化成引用类型这个方法叫做装箱boxing。相反把引用类型转成基本类型就叫拆箱装箱是有性能代价的装箱后的值本质上就是把基本类型包裹起来并保存在堆里。因此装箱后的值需要更多的内存并需要额外的内存搜索来获取被包裹的基本值。在下面的代码中使用 IntPredicate 就避免了对值 1000 进行装箱操作但要是用 Predicate就会把参数 1000 装箱到一个 Integer 对象中 public interface IntPredicate { boolean test(int t);
}
// true无装箱
IntPredicate evenNumbers (int i) - i % 2 0;
evenNumbers.test(1000);
// false装箱
PredicateInteger oddNumbers (Integer i) - i % 2 ! 0;
oddNumbers.test(1000); 一般来说针对专门的输入参数类型的函数式接口的名称都要加上对应的基本类型前缀比如 DoublePredicate、IntConsumer、LongBinaryOperator、IntFunction 等。Function接口还有针对输出参数类型的变种ToIntFunction、IntToDoubleFunction 等。
3.5 类型检查、类型推断以及限制 3.5.1 类型检查
Lambda 的类型是从使用 Lambda 的上下文推断出来的。上下文比如接受它传递的方法的参数或接受它的值的局部变量中 Lambda 表达式需要的类型称为目标类型。例子ListApple heavierThan150g filter(inventory, (Apple apple) - apple.getWeight() 150);类型检查过程分解如下。
你要找出 filter 方法的声明。要求它是 Predicate目标类型对象的第二个正式参数。Predicate是一个函数式接口定义了一个叫作 test 的抽象方法。test 方法描述了一个函数描述符它可以接受一个 Apple并返回一个 boolean。filter 的任何实际参数都必须匹配这个要求。 3.5.2 同样的 Lambda不同的函数式接口
有了目标类型的概念同一个 Lambda 表达式就可以与不同的函数式接口联系起来只要它们的抽象方法签名能够兼容。CallableInteger c () - 42; PrivilegedActionInteger p () - 42;
3.5.3 类型推断
Java 编译器会从上下文目标类型推断出用什么函数式接口来配合 Lambda 表达式这意味着它也可以推断出适合 Lambda 的签名参数 apple 没有显式类型ListApple greenApples filter(inventory, apple - GREEN.equals(apple.getColor()));可以这样来创建一个Comparator 对象没有类型推断ComparatorApple c (Apple a1, Apple a2) - a1.getWeight().compareTo(a2.getWeight()); 有类型推断ComparatorApple c (a1, a2) - a1.getWeight().compareTo(a2.getWeight());
3.5.4 使用局部变量
我们迄今为止所介绍的所有 Lambda 表达式都只用到了其主体里面的参数。但 Lambda 表达式也允许使用自由变量不是参数而是在外层作用域中定义的变量就像匿名类一样。int portNumber 1337; Runnable r () - System.out.println(portNumber);Lambda 可以没有限制地捕获也就是在其主体中引用实例变量和静态变量。但局部变量必须显式声明为 final或事实上是 final。
下面这个例子是错误的int portNumber 1337; Runnable r () - System.out.println(portNumber);portNumber 31337; 因为Lambda 表达式引用的局部变量必须是最终的final或事实上最终的对局部变量的限制实例变量和局部变量背后的实现有一个关键不同。实例变量都存储在堆中局部变量则保存在栈上。这一限制不鼓励你使用改变外部变量的典型命令式编程模式。方法引用。可以把它们视为某些Lambda 的快捷写法。
3.6 方法引用
方法引用让你可以重复使用现有的方法定义并像 Lambda 一样传递它们。先前inventory.sort((Apple a1, Apple a2) a1.getWeight().compareTo(a2.getWeight())); 之后使用方法引用和 java.util.Comparator.comparinginventory.sort(comparing(Apple::getWeight));
3.6.1 管中窥豹
如果一个 Lambda 代表的只是“直接调用这个方法”那最好还是用名称来调用它而不是去描述如何调用它。方法引用就是让你根据已有的方法实现来创建Lambda 表达式。但是显式地指明方法的名称你的代码的可读性会更好。当你需要使用方法引用时目标引用放在分隔符::前方法的名称放在后面。例如Apple::getWeight 就是引用了 Apple 类中定义的方法 getWeight。getWeight 后面不需要括号因为你没有实际调用这个方法只是引用了它的名称。
Lambda 表达式重构为等价方法引用的简易速查表
ListString str Arrays.asList(a,b,A,B);
str.sort((s1, s2) - s1.compareToIgnoreCase(s2)); Lambda 表达式的签名与 Comparator 的函数描述符兼容 可以修改成这样的
str.sort(String::compareToIgnoreCase); 测验 3.6方法引用 下列 Lambda 表达式的等效方法引用是什么 (1) ToIntFunction stringToInt (String s) - Integer.parseInt(s); (2) BiPredicateList, String contains (list, element) - list.contains(element); (3) Predicate startsWithNumber (String string) - this .startsWithNumber(string); 答案(1) 这个 Lambda 表达式将其参数传给了 Integer 的静态方法 parseInt。这种方法接受一个需要解析的 String并返回一个 Integer。因此可以使用图 3-5 中的办法➊Lambda 表达式调用静态方法来重写 Lambda 表达式如下所示**ToIntFunction stringToInt Integer::parseInt; ** (2) 这个 Lambda 使用其第一个参数调用其 contains 方法。由于第一个参数是 List类型的因此你可以使用图 3-5 中的办法➋如下所示BiPredicateList, String contains List::contains; 这是因为目标类型描述的函数描述符是(List,String) - boolean而List::contains 可以被解包成这个函数描述符。 (3) 这种“表达式–风格”的 Lambda 会调用一个私有方法。你可以使用图 3-5 中的办法❸如下所示 Predicate startsWithNumber this::startsWithNumber 3.6.2 构造函数引用
对于一个现有构造函数你可以利用它的名称和关键字 new 来创建它的一个引用ClassName::new。它的功能与指向静态方法的引用类似。例如假设有一个构造函数没有参数。它适合 Supplier 的签名() - Apple。你可以这样做
ListInteger weights Arrays.asList(7, 3, 4, 10);
ListApple apples map(weights, Apple::new); // 将构造函数引用传递给 map 方法
public ListApple map(ListInteger list, FunctionInteger, Apple f) { ListApple result new ArrayList(); for(Integer i: list) { result.add(f.apply(i)); } return result;
}
如果你有一个具有两个参数的构造函数 Apple(String color, Integer weight)那么它就适合 BiFunction 接口的签名于是你可以这样写
如果有构造参数 那么Apple::new;这样返回一个对象怎么知道我的构造参数呢 测验 3.7构造函数引用 你已经看到了如何将有零个、一个、两个参数的构造函数转变为构造函数引用。那要怎么样才能对具有三个参数的构造函数比如 RGB(int, int, int)使用构造函数引用呢 答案你看构造函数引用的语法是 ClassName::new那么在这个例子里面就是 RGB::new。但是你需要与构造函数引用的签名匹配的函数式接口。由于语言本身并没有提供这样的函数式接口因此你可以自己创建一个 public interface TriFunctionT, U, V, R { R apply(T t, U u, V v); } 现在你可以像下面这样使用构造函数引用了 TriFunctionInteger, Integer, Integer, RGB colorFactory RGB::new; 3.7 Lambda 和方法引用实战
用不同的排序策略给一个 Apple 列表排序并需要展示如何把一个原始粗暴的解决方案转变得更为简明。这会用到书中迄今讲到的所有概念和功能行为参数化、匿名类、Lambda表达式和方法引用。我们想要实现的最终解决方案是这样的inventory.sort(comparing(Apple::getWeight));
3.7.1 第 1 步传递代码
Java 8 API 已经为你提供了一个 List 可用的 sort 方法。那么最困难的部分已经搞定了但是如何把排序策略传递给 sort 方法呢sort 方法的签名是这样的void sort(Comparator? super E c) sort 的行为被参数化了传递给它的排序策略不同其行为也会不同。方案
public class AppleComparator implements ComparatorApple { public int compare(Apple a1, Apple a2){ return a1.getWeight().compareTo(a2.getWeight());}
}
inventory.sort(new AppleComparator()); 3.7.2 第 2 步使用匿名类
使用匿名内部类修改
inventory.sort(new ComparatorApple() { public int compare(Apple a1, Apple a2){ return a1.getWeight().compareTo(a2.getWeight()); }
}); 3.7.3 第 3 步使用 Lambda 表达式
lambda传递代码方式函数式接口inventory.sort((Apple a1, Apple a2) - a1.getWeight().compareTo(a2.getWeight())); Java 编译器可以根据 Lambda 出现的上下文来推断 Lambda 表达式参数的类型。那么可以重写成这样inventory.sort((a1, a2) - a1.getWeight().compareTo(a2.getWeight())); Comparator 具有一个叫作 comparing 的静态辅助方法它可以接受一个 Function 来提取 Comparable 键值并生成一个 Comparator 对象ComparatorApple c Comparator.comparing((Apple a) - a.getWeight()); 可以改成这样import static java.util.Comparator.comparing; // 静态导入inventory.sort(comparing(apple - apple.getWeight())); 3.7.4 第 4 步使用方法引用
假设你静态导入了 java.util.Comparator.comparinginventory.sort(comparing(Apple::getWeight));
3.8 复合 Lambda 表达式的有用方法
Java 8 的好几个函数式接口都有为方便而设计的方法。具体而言许多函数式接口比如用于传递 Lambda 表达式的 Comparator、Function 和 Predicate 都提供了允许你进行复合的方法。
3.8.1 比较器复合
我们前面看到你可以使用静态方法 Comparator.comparing根据提取用于比较的键值的 Function 来返回一个 Comparator如下所示ComparatorApple c Comparator.comparing(Apple::getWeight);
逆序
用不着去建立另一个 Comparator 的实例。接口有一个默认方法 reversed 可以使给定的比较器逆序inventory.sort(comparing(Apple::getWeight).**reversed**()); // 按重量递减排序
比较器链
如果苹果一样重呢需要进一步的按照其他属性排序如果两个对象用第一个 Comparator 比较之后是一样的就提供第二个 Comparator。你又可以优雅地解决这个问题了
inventory.sort(comparing(Apple::getWeight) .reversed() // 按重量递减排序.thenComparing(Apple::getCountry)); // 两个苹果一样重时进一步按国家排序3.8.2 谓词复合
谓词接口包括三个方法negate、and 和 or让你可以重用已有的 Predicate 来创建更复杂的谓词。比如你可以使用 negate 方法来返回一个 Predicate 的非比如苹果不是红的// 产生现有 Predicate对象 redApple 的非**PredicateApple notRedApple redApple.negate();**想要把两个 Lambda 用 and 方法组合起来比如一个苹果既是红色又比较重// 链接两个谓词来生成另一个 Predicate 对象PredicateApple redAndHeavyApple redApple.and(apple - apple.getWeight() 150);进一步组合谓词表达要么是重150 克以上的红苹果要么是绿苹果Predicate redAndHeavyAppleOrGreen redApple.and(apple - apple.getWeight() 150) .or(apple - GREEN.equals(a.getColor())); and 和 or 方法是按照在表达式链中的位置从左向右确定优先级的。因此a.or(b).and©可以看作(a || b) c。同样a.and(b).or© 可以看作(a b) || c。 3.8.3 函数复合
还可以把 Function 接口所代表的 Lambda 表达式复合起来。Function 接口为此配了 andThen 和 compose 两个默认方法它们都会返回 Function 的一个实例。andThen 方法会返回一个函数它先对输入应用一个给定函数再对输出应用另一个函数。
FunctionInteger, Integer f x - x 1; // 函数 f 给数字加 1 (x - x 1)
FunctionInteger, Integer g x - x * 2; // 函数 g 给数字乘 2
// 数学上会写作 g(f(x))或(g o f)(x)
FunctionInteger, Integer h f.andThen(g); // 组合成一个函数 h先给数字加 1再给结果乘 2
int result h.apply(1); // 返回 4也可以类似地使用 compose 方法先把给定的函数用作 compose 的参数里面给的那个函数然后再把函数本身用于结果
FunctionInteger, Integer f x - x 1;
FunctionInteger, Integer g x - x * 2;
// 数学上会写作 f(g(x))或(f o g)(x)
FunctionInteger, Integer h f.compose(g);
int result h.apply(1); // 返回 3andThen 和 compose 之间的区别。
实际使用比方说你有一系列工具方法对用 String 表示的一封信做文本转换
public class Letter{ public static String addHeader(String text){ return From Raoul, Mario and Alan: text; } public static String addFooter(String text){ return text Kind regards; } public static String checkSpelling(String text){ return text.replaceAll(labda, lambda); }
} 可以通过复合这些工具方法来创建各种转型流水线了比如创建一个流水线先加上抬头然后进行拼写检查最后加上一个落款如图 3-7 所示。
FunctionString, String addHeader Letter::addHeader;
FunctionString, String transformationPipeline addHeader.andThen(Letter::checkSpelling) .andThen(Letter::addFooter); 第二个流水线可能只加抬头、落款而不做拼写检查 FunctionString, String addHeader Letter::addHeader;
FunctionString, String transformationPipeline addHeader.andThen(Letter::addFooter); 3.9 数学中的类似思想 3.9.1 积分
数学函数f (x) x 10求函数下方的面积
3.9.2 与 Java 8 的 Lambda 联系起来
Java 8 的表示法(double x) - x 10一个 Lambda 表达式恰恰就是为此设计的因此你可以写**integrate((double x) - x 10, 3, 7) **或者**integrate((double x) - f(x), 3, 7) **或者使用方法引用的方式**integrate(C::f, 3, 7) **// 这里 C 是包含静态方法 f 的一个类。理念就是把 f 背后的代码传给 integrate 方法。integrate 方法本身数学的形式。Java函数的写法不能像数学里那样
public double integrate((double - double) f, double a, double b) {return (f(a) f(b)) * (b - a) / 2.0
}或者用 DoubleUnaryOperator这样也可以避免对结果进行装箱
public double integrate(DoubleUnaryOperator f, double a, double b) { return (f.applyAsDouble(a) f.applyAsDouble(b)) * (b - a) / 2.0;
} 有点可惜的是你必须写 f.apply(a)而不是像数学里面写 f(a)但 Java 无法摆脱“一切都是对象”的思想——它不能让函数完全独立
3.10 小结
Lambda 表达式可以理解为一种匿名函数它没有名称但有参数列表、函数主体、返回类型可能还有一个可以抛出的异常的列表。Lambda 表达式让你可以简洁地传递代码。函数式接口就是仅仅声明了一个抽象方法的接口。只有在接受函数式接口的地方才可以使用 Lambda 表达式。Lambda 表达式允许你直接内联为函数式接口的抽象方法提供实现并且将整个表达式作为函数式接口的一个实例。Java 8自带一些常用的函数式接口放在 java.util.function 包里包括 Predicate 、FunctionT, R、Supplier、Consumer和 BinaryOperator如表 3-2所述。为了避免装箱操作对 Predicate和 FunctionT, R等通用函数式接口的基本类型特化IntPredicate、IntToLongFunction 等。环绕执行模式即在方法所必需的代码中间你需要执行点儿什么操作比如资源分配和清理可以配合 Lambda 提高灵活性和可重用性。Lambda 表达式所需要代表的类型称为目标类型。方法引用让你重复使用现有的方法实现并直接传递它们。Comparator、Predicate 和 Function 等函数式接口都有几个可以用来结合 Lambda表达式的默认方法。 文章转载自: http://www.morning.qbdsx.cn.gov.cn.qbdsx.cn http://www.morning.jcrlx.cn.gov.cn.jcrlx.cn http://www.morning.mqnbm.cn.gov.cn.mqnbm.cn http://www.morning.nyqm.cn.gov.cn.nyqm.cn http://www.morning.nsyzm.cn.gov.cn.nsyzm.cn http://www.morning.ttnfc.cn.gov.cn.ttnfc.cn http://www.morning.glnxd.cn.gov.cn.glnxd.cn http://www.morning.mzzqs.cn.gov.cn.mzzqs.cn http://www.morning.lltdf.cn.gov.cn.lltdf.cn http://www.morning.lhzqn.cn.gov.cn.lhzqn.cn http://www.morning.nkqxb.cn.gov.cn.nkqxb.cn http://www.morning.ynrzf.cn.gov.cn.ynrzf.cn http://www.morning.yfddl.cn.gov.cn.yfddl.cn http://www.morning.khcpx.cn.gov.cn.khcpx.cn http://www.morning.pudejun.com.gov.cn.pudejun.com http://www.morning.nkqnn.cn.gov.cn.nkqnn.cn http://www.morning.zxdhp.cn.gov.cn.zxdhp.cn http://www.morning.wbqt.cn.gov.cn.wbqt.cn http://www.morning.wqpb.cn.gov.cn.wqpb.cn http://www.morning.mrcpy.cn.gov.cn.mrcpy.cn http://www.morning.ckrnq.cn.gov.cn.ckrnq.cn http://www.morning.mwlxk.cn.gov.cn.mwlxk.cn http://www.morning.jcwhk.cn.gov.cn.jcwhk.cn http://www.morning.snnb.cn.gov.cn.snnb.cn http://www.morning.npqps.cn.gov.cn.npqps.cn http://www.morning.hrhwn.cn.gov.cn.hrhwn.cn http://www.morning.lgnrl.cn.gov.cn.lgnrl.cn http://www.morning.nbsfb.cn.gov.cn.nbsfb.cn http://www.morning.fmtfj.cn.gov.cn.fmtfj.cn http://www.morning.xzsqb.cn.gov.cn.xzsqb.cn http://www.morning.dmlgq.cn.gov.cn.dmlgq.cn http://www.morning.jglqn.cn.gov.cn.jglqn.cn http://www.morning.kjgrg.cn.gov.cn.kjgrg.cn http://www.morning.qbmjf.cn.gov.cn.qbmjf.cn http://www.morning.hjjkz.cn.gov.cn.hjjkz.cn http://www.morning.fwnyz.cn.gov.cn.fwnyz.cn http://www.morning.btlmb.cn.gov.cn.btlmb.cn http://www.morning.gjlml.cn.gov.cn.gjlml.cn http://www.morning.mlbdr.cn.gov.cn.mlbdr.cn http://www.morning.cldgh.cn.gov.cn.cldgh.cn http://www.morning.lxthr.cn.gov.cn.lxthr.cn http://www.morning.dtzxf.cn.gov.cn.dtzxf.cn http://www.morning.fgsct.cn.gov.cn.fgsct.cn http://www.morning.tmlhh.cn.gov.cn.tmlhh.cn http://www.morning.kxqmh.cn.gov.cn.kxqmh.cn http://www.morning.ktnmg.cn.gov.cn.ktnmg.cn http://www.morning.gcspr.cn.gov.cn.gcspr.cn http://www.morning.zdxinxi.com.gov.cn.zdxinxi.com http://www.morning.bybhj.cn.gov.cn.bybhj.cn http://www.morning.zmnyj.cn.gov.cn.zmnyj.cn http://www.morning.jtmql.cn.gov.cn.jtmql.cn http://www.morning.lgpzq.cn.gov.cn.lgpzq.cn http://www.morning.mxnfh.cn.gov.cn.mxnfh.cn http://www.morning.jsphr.cn.gov.cn.jsphr.cn http://www.morning.wrdlf.cn.gov.cn.wrdlf.cn http://www.morning.qggcc.cn.gov.cn.qggcc.cn http://www.morning.txfxy.cn.gov.cn.txfxy.cn http://www.morning.xtdtt.cn.gov.cn.xtdtt.cn http://www.morning.tdqhs.cn.gov.cn.tdqhs.cn http://www.morning.cqrenli.com.gov.cn.cqrenli.com http://www.morning.lwhsp.cn.gov.cn.lwhsp.cn http://www.morning.nbgfk.cn.gov.cn.nbgfk.cn http://www.morning.wblpn.cn.gov.cn.wblpn.cn http://www.morning.yprjy.cn.gov.cn.yprjy.cn http://www.morning.fflnw.cn.gov.cn.fflnw.cn http://www.morning.ebpz.cn.gov.cn.ebpz.cn http://www.morning.trsfm.cn.gov.cn.trsfm.cn http://www.morning.xrksf.cn.gov.cn.xrksf.cn http://www.morning.qbpqw.cn.gov.cn.qbpqw.cn http://www.morning.rzrbw.cn.gov.cn.rzrbw.cn http://www.morning.nppml.cn.gov.cn.nppml.cn http://www.morning.xmyrn.cn.gov.cn.xmyrn.cn http://www.morning.pqchr.cn.gov.cn.pqchr.cn http://www.morning.ljxxl.cn.gov.cn.ljxxl.cn http://www.morning.pflpb.cn.gov.cn.pflpb.cn http://www.morning.tmxfn.cn.gov.cn.tmxfn.cn http://www.morning.pjbhk.cn.gov.cn.pjbhk.cn http://www.morning.hqzmz.cn.gov.cn.hqzmz.cn http://www.morning.ymbqr.cn.gov.cn.ymbqr.cn http://www.morning.ldfcb.cn.gov.cn.ldfcb.cn