在一文中,我们对
里的每一位联系人调用
- Stream<Contact>
方法,并根据能否打通的返回结果过滤掉已经失效的项。
- call()
应该注意到此时
中 Lambda 的写法有些特殊:
- filter(..)
- // ...
- .filter(Contact: :call)
- // ...
在确定了
中每一个元素的类型后,如果使用
- Stream<T>
并为谓词演算提供参数的唯一用途就是将这个参数再提供给一个方法,那么参数列表在已经确定的情况下就基本没有存在的必要:
- filter(..)
- filter(Predicatesuper T> predicate)
而
中的抽象方法(目标方法):
- Predicate<T>
- boolean test(T t)
编译器能够推断出,Lambda 体会传入一个类型为
(或其父类)的参数,并对这个参数调用某个(或是实例或是某个类的静态)方法(此处应该是所有符合
- T
接口中
- Predicate
的方法),在这种情况下我们只需要给出那个方法是什么即可,不必大费周章地去传递这个参数。
- test(..)
只需要给出类名以及静态方法名即可,中间用双冒号分隔,如:
- MyLogger: :log // s -> MyLogger.log(s)
一个简单的示例,使用自定义的日志工具输出内容:
- Arrays.asList("We will build a great wall and Mexico will pay."
- .split(" "))
- .forEach(MyLogger::log);
就是
- log(..)
类中的静态方法,
- MyLogger
则给 Lambda 提供了
- forEach(..)
类型的参数,当然了,
- String
接收的也是单个字符串作为参数,这样才能与之完美匹配:
- log(..)
- private static void log(String content) {
- System.out.println("=> " + content);
- }
这样的操作方法不仅仅只限制于单个参数的参数列表:
- List bullshits = Arrays.asList("Make America Great Again".split(" "));
- bullshits.sort(MyTrumpBullshitComparator::doMyCompare);
因为
会一次给出两个参数供互相比较,所以我们需要构造一个接收两个
- sort(..)
类型参数的静态方法:
- String
- private static int
- doMyCompare(String toBeCompared, String toBeComparedTo) {
- return toBeCompared.compareTo(toBeComparedTo);
- }
绑定引用的接收者是一个具体的对象实例。
就是再将静态方法引用中的静态方法名换成了实例方法名?
看上去似乎是这样,然而...
绑定方法引用仅仅在格式上类似于静态方法引用,使用双冒号将对象引用与其实例方法名隔开:
- List idiots = Arrays.stream("Trump-Pence"
- .split("-"))
- .map(MyIdiotNameModifier.upperCaser::toUpperCase)
- .collect(Collectors.toList());
对流中的每个名字调用了
类中的静态实例
- MyIdiotNameModifier
的实例方法
- upperCaser
。
- toUpperCase(..)
这个例子实在有些牵强,我是模仿了
做出来的,为了表现对某个已经确定的实例引用其实例方法:
- System.out.println(..)
- final class MyIdiotNameModifier {
- static final UpperCaser upperCaser = new UpperCaser();
- }
- class UpperCaser {
- String toUpperCase(String string) {
- return string.toUpperCase();
- }
- }
类比 sout:
- // s -> MyIdiotNameModifier.upperCaser.toUpperCase(s)
- MyIdiotNameModifier.upperCaser::toUpperCase
- // s -> System.out.println(s)
- System.out::println
就是说如果我们引用了
,那么这个引用的接受者已经能够确定是
- toUpperCase(..)
类中的静态实例
- MyIdiotNameModifier
。
- upperCaser
然而更魔性的东西来了,某些情况下不能够确定与实例的绑定关系。
不知道对谁调用引用的方法,那么只能排着队按顺序分配了,在只给出一个参数的时候,看起来就很明显——这个参数直接分配给绑定引用:
- // 摘自推特账号@realDonaldTrump
- Arrays.asList(
- "The President Changed. So Has Small Businesses' Confidence",
- "Great meeting with the @RepublicanStudy Committee this morning at the @WhiteHouse!",
- "North Korea is behaving very badly. They have been \"playing\" the United States for years. China has done little to help!")
- .forEach(String::toUpperCase);
每一条推文都被传给引用
,并对自身调用了这个方法。
- toUpperCase
在这里我们不能确定引用的对象的标识符是什么(因为我们省略了传入的参数表),所以干脆将它的类型
写出来,告诉编译器我们会对一个
- String
类型的接收者调用它的
- String
方法。
- toUpperCase(..)
这种引用使用
关键字代替方法名即可,但是前面需要使用的是类名而非某个对象实例的标识符:
- new
- // s -> new String(s)
- String::new
关于绑定与非绑定的区别,这里一定要摘录一下书中所给的例子,因为它简直堪称绝妙,自己看了很久才明白过来。
首先给出:
- static final String string = "alpha-bravo-charlie";
然后,为了保证输出的顺序,我们实例化一个
:
- TreeMap<K, V>
- private static Map stringStringMap = new TreeMap() {
- {
- put("alpha", "X");
- put("bravo", "Y");
- put("charlie", "Z");
- }
- };
注意 map 里的键和一开始给出的字符串的对应关系。
- stringStringMap.replaceAll(string::replace);
输出:
- {
- alpha=X-bravo-charlie,
- bravo=alpha-Y-charlie,
- charlie=alpha-bravo-Z
- }
很明显,这里我们需要一个二元函数,并返回一个结果。
map 中每一项的 key 作为第一个参数传入,与其对应的 value 作为第二个参数传入,而对对象实例
的方法引用
- string
正是一个二元函数,也同时返回替换后作为结果的字符串。
- string::replace
为此我特意去看了
类的
- Map
的源码,根本就和
- replaceAll(..)
类的那种
- String
不是一回事...
- replaceAll(..)
首先是拿到一个自己的迭代器,然后开始迭代——如果有下一项的话取这一项(同时指针后移),并拿到这一项的键和值,随后将这两个量作为参数传递给传入
的二元函数
- replaceAll(..)
(在这里就是
- BiFunction<? super K, ? super V, ? extends V>
),并将运算结果作为新值写进当前项(键不变),接着开始下一轮迭代...
- string::replace
这里做了张图,不准确,但是大概是这么个样子...
- stringStringMapB.replaceAll(String::concat);
输出:
- {
- alpha = alphaX,
- bravo = bravoY,
- charlie = charlieZ
- }
我们都知道
只接收一个参数,但是在这里显然应该放置一个二元函数,那么这种写法是否会出错呢,答案是否定的。
- concat(..)
注意观察我们会发现,这里对
方法的引用变成了非绑定的形式,也就是说,在
- concat(..)
入参之前,还需要解决这个双冒号前面的
- concat(..)
是谁的问题,此时
- String
给出的 key、value 参数将会向参数列表的前面挪一位,用于填补非绑定带来的空缺。
- replaceAll(..)
也就是说,此时 key 变成了
引用的接收者,而 value 则成为了此方法所需要的唯一参数...
- concat(..)
同样做了一个貌似不怎么准确的图:
弄完图发现已经快一点半了,虽说是周末但是防止我猝死还是先到这了吧...
MC.java
- import java.util.Arrays;
- import java.util.List;
- import java.util.stream.Collectors;
- /**
- * Created by hwding on 3/18/17.
- */
- public class MC {
- public static void main(String[] args) {
- Arrays.asList("We will build a great wall and Mexico will pay."
- .split(" "))
- .forEach(MyLogger::log);
- List bullshits =
- Arrays.asList("Make America Great Again"
- .split(" "));
- bullshits
- .sort(MyTrumpBullshitComparator::doMyCompare);
- System.out.println("\n" + bullshits + "\n");
- List idiots = Arrays.stream("Trump-Pence"
- .split("-"))
- .map(MyIdiotNameModifier.upperCaser::toUpperCase)
- .collect(Collectors.toList());
- idiots.forEach(System.out::println);
- Arrays.asList(
- "The President Changed. So Has Small Businesses' Confidence",
- "Great meeting with the @RepublicanStudy Committee this morning at the @WhiteHouse!",
- "North Korea is behaving very badly. They have been \"playing\" the United States for years. China has done little to help!")
- .forEach(String::toUpperCase);
- }
- private static class MyLogger {
- private static void log(String content) {
- System.out.println("=> " + content);
- }
- }
- private static class MyTrumpBullshitComparator {
- private static int
- doMyCompare(String toBeCompared, String toBeComparedTo) {
- return toBeCompared.compareTo(toBeComparedTo);
- }
- }
- }
以及其运行结果:
- => We
- => will
- => build
- => a
- => great
- => wall
- => and
- => Mexico
- => will
- => pay.
- [Again, America, Great, Make]
- TRUMP
- PENCE
EX.java
- import java.util.Map;
- import java.util.TreeMap;
- /**
- * Created by hwding on 3/19/17.
- */
- public class EX {
- static final String string = "alpha-bravo-charlie";
- private static Map stringStringMap = new TreeMap() {
- {
- put("alpha", "X");
- put("bravo", "Y");
- put("charlie", "Z");
- }
- };
- private static Map stringStringMapB = new TreeMap() {
- {
- put("alpha", "X");
- put("bravo", "Y");
- put("charlie", "Z");
- }
- };
- public static void main(String[] args) {
- stringStringMap.replaceAll(string: :replace);
- System.out.println(stringStringMap);
- stringStringMapB.replaceAll(String: :concat);
- System.out.println(stringStringMapB);
- }
- }
以及其运行结果:
- {
- alpha = X - bravo - charlie,
- bravo = alpha - Y - charlie,
- charlie = alpha - bravo - Z
- } {
- alpha = alphaX,
- bravo = bravoY,
- charlie = charlieZ
- }
MyIdiotNameModifier.java
- /**
- * Created by hwding on 3/18/17.
- */
- final class MyIdiotNameModifier {
- static final UpperCaser upperCaser = new UpperCaser();
- }
- class UpperCaser {
- String toUpperCase(String string) {
- return string.toUpperCase();
- }
- }
来源: http://www.cnblogs.com/hwding/p/6580010.html