当前位置: 首页 > news >正文

上饶时时彩网站建设域名查询入口

上饶时时彩网站建设,域名查询入口,秀屿区建设局网站,网页设计素材代码包作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO 联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬 引子 先来看一个案例 …
作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬

引子

先来看一个案例

public class MethodReferenceTest {private static final List<Person> list;static {list = new ArrayList<>();list.add(new Person(19));list.add(new Person(18));list.add(new Person(20));}public static void main(String[] args) {System.out.println(list);// sort()方法是List本身就有的,主要用来排序list.sort((p1, p2) -> p1.getAge() - p2.getAge());System.out.println(list);}@Data@AllArgsConstructorstatic class Person {private Integer age;}}

结果

排序前:

[MethodReferenceTest.Person(age=19), MethodReferenceTest.Person(age=18), MethodReferenceTest.Person(age=20)]

排序后:

[MethodReferenceTest.Person(age=18), MethodReferenceTest.Person(age=19), MethodReferenceTest.Person(age=20)]

把上面的案例稍作改动:

public class MethodReferenceTest {private static final List<Person> list;static {list = new ArrayList<>();list.add(new Person(19));list.add(new Person(18));list.add(new Person(20));}public static void main(String[] args) {System.out.println(list);// 改动2:既然Person内部有个逻辑一样的方法,就用它来替换Lambdalist.sort(Person::compare);System.out.println(list);}@Data@AllArgsConstructorstatic class Person {private Integer age;// 改动1:新增一个方法,逻辑和之前案例的Lambda表达式相同public static int compare(Person p1, Person p2) {return p1.getAge() - p2.getAge();}}
}

嗯?这是什么操作?不急,接着往下看。

从Lambda到方法引用

大家在《Lambda表达式》一文中应该看过下面这段代码:

/*** 从匿名对象 到Lambda 再到方法引用** @author mx*/
public class MethodReferenceTest {public static void main(String[] args) {String str1 = "abc";String str2 = "abcd";// 方式1:匿名对象Comparator<String> comparator1 = new Comparator<String>() {@Overridepublic int compare(String o1, String o2) {return o1.length() - o2.length();}};compareString(str1, str2, comparator1);// 方式2:过渡为Lambda表达式Comparator<String> comparator2 = (String s1, String s2) -> {return s1.length() - s2.length();};compareString(str1, str2, comparator2);// 方式2的改进版:省去赋值操作,直接把整个Lambda表达式作为参数丢进去compareString(str1, str2, (String s1, String s2) -> {return s1.length() - s2.length();});// 方式2的最终版:把变量类型和return也去掉了,因为Java可以自动推断compareString(str1, str2, (s1, s2) -> s1.length() - s2.length());// 方式3:换种比较方式,本质和方式2是一样的,不信你去看看String#compareTo()Comparator<String> comparator3 = (s1, s2) -> s1.compareTo(s2);// 方式4:IDEA提示有改进的写法,最终变成了方法引用compareString(str1, str2, String::compareTo);// 完美。}/*** 传递Comparator,对str1和str2进行比较** @param str1* @param str2* @param comparator*/public static void compareString(String str1, String str2, Comparator<String> comparator) {System.out.println(comparator.compare(str1, str2));}
}

很多初学者肯定崩溃了:Lambda已经够抽象了,好不容易从匿名对象过渡到Lambda,怎么又突然冒出String::compareTo这鬼东西?!

我们在学习Lambda时,把它和匿名类作比较。因为匿名类和Lambda处理的逻辑是一样的,所以就用Lambda简化了匿名类:

同样的,如果项目中已经定义了相同逻辑的方法,我们为什么还要再写一遍呢?即使Lambda表达式再怎么简洁,终究还是要手写好几行代码。

所以,JDK在Lambda表达式的基础上又提出了方法引用的概念,允许我们复用当前项目(或JDK源码)中已经存在的且逻辑相同的方法。

比如上面那个例子中的:

// 方式3:换种比较方式,本质和方式2是一样的
Comparator<String> comparator3 = (s1, s2) -> s1.compareTo(s2);// 方式4:IDEA提示有改进的写法,最终变成了方法引用
compareString(str1, str2, String::compareTo);

String::compareTo看起来形式有点诡异,但这只是一种语法而已,习惯就好了,关键是明白它代表什么意思。Java8引入::符号,用来表示方法引用。所谓的方法引用,就是把方法搬过来使用。那么,String::compareTo把哪个类的什么方法搬过来了呢?

一般来说,String类定义的compareTo方法的正常使用方式是这样的:

public class MethodReferenceTest {public static void main(String[] args) {String str = "hello";String anotherStr = "world";int difference = str.compareTo(anotherStr);}
}

作为更高阶的Lambda表达式,方法引用也能作为参数传递,于是就有了:

public class MethodReferenceTest {public static void main(String[] args) {String str = "hello";String anotherStr = "world";// 匿名内部类Comparator<String> comparator = new Comparator<String>() {@Overridepublic int compare(String str, String anotherStr) {return str.compareTo(anotherStr);}};// 方法引用。上面的str.compareTo(anotherStr)不就是String::compareTo吗!!Comparator<String> newComparator = String::compareTo;compareString(str, anotherStr, newComparator);}/*** 传递Comparator,对str1和str2进行比较** @param str1* @param str2* @param comparator*/public static void compareString(String str1, String str2, Comparator<String> comparator) {System.out.println(comparator.compare(str1, str2));}
}

总之,Java8的意思就是:

兄弟,如果已经存在某个方法能完成你的需求,那么你连Lambda表达式都别写了,直接引用这个方法吧。

但我个人更推荐Lambda表达式,原因有两个:

  • 对初学者而言,Lambda表达式语义更清晰、更好理解
  • Lambda表达式细粒度更小,能完成更精细的需求

第一点,你懂的。

第二点,请容许我来证明一下。

Lambda表达式VS方法引用

/*** MyPredict是模拟Predict* MyInteger是模拟Integer* <p>* 本次测试的目的旨在说明:Lambda毕竟是手写的,自由度和细粒度要高于方法引用。** @author sunting*/
public class MethodAndLambdaTest {public static void main(String[] args) {// 1.匿名对象MyPredict myPredict1 = new MyPredict() {@Overridepublic boolean test(int a, int b) {return a - b > 0;}};boolean result1 = myPredict1.test(1, 2); // false// 2.从匿名对象过渡到Lambda表达式MyPredict myPredict2 = (a, b) -> a - b > 0;myPredict2.test(1, 2); // false// 3.MyInteger#compare()的方法体和上面的Lambda表达式逻辑相同,可以直接引用MyPredict myPredict3 = MyInteger::compare;myPredict3.test(1, 2); // false// 4.Lambda说,你想模仿我?想得美!老子要DIY一下比较规则(a减b 变成了 b减a)MyPredict myPredict4 = (a, b) -> b - a > 0;myPredict4.test(1, 2); // true// 5.看到这,方法引用不服气,也想DIY一把MyPredict myPredict5 = MyInteger::compare;// ???,没法DIY,MyInteger::compare是把整个方法搬过来,不能修改内部的逻辑}
}interface MyPredict {boolean test(int a, int b);
}class MyInteger {public static boolean compare(int a, int b) {return a - b > 0;}
}

方法引用,其实就是把现成的某个方法拿来替代逻辑相似的Lambda表达式。

但Lambda表达式由(a, b) -> a - b > 0 变为 (a, b) -> b - a > 0 ,说明Lambda逻辑已经变了,此时原先的方法引用就不匹配了,不能再用了。此时我们最自然的想法应该是从现成的项目中找到逻辑和(a, b) -> b - a > 0相同的另一个方法,然后把那个方法引用过来,而不是想着改变原来的MyInteger::Compare,那不是你的方法,你也只是借用而已!!

所以,我们给MyInteger加一个方法吧:

class MyInteger {public static boolean compare(int a, int b) {return a - b > 0;}public static boolean anotherCompare(int a, int b) {return b - a > 0;}
}

这样,方法引用的逻辑又和Lambda匹配了:

public class MethodAndLambdaTest {public static void main(String[] args) {MyPredict myPredict2 = (a, b) -> a - b > 0;myPredict2.test(1, 2); // falseMyPredict myPredict3 = MyInteger::compare;myPredict3.test(1, 2); // falseMyPredict myPredict4 = (a, b) -> b - a > 0;myPredict4.test(1, 2); // true// MyInteger::anotherCompare的逻辑和上面的Lambda才是匹配的MyPredict myPredict5 = MyInteger::anotherCompare;myPredict5.test(1, 2); // true}}interface MyPredict {boolean test(int a, int b);
}class MyInteger {public static boolean compare(int a, int b) {return a - b > 0;}public static boolean anotherCompare(int a, int b) {return b - a > 0;}
}

再看一个Stream API的例子:

filter此时需要的逻辑是:年龄大于等于30岁的teacher。

你能从现有项目中找到逻辑为“年龄大于等于30岁的teacher”的方法吗?

答案是没有。

你最多只能调用Teacher::getAge(),但是这个方法引用的逻辑是“获取老师的年龄”,而不是“是否大于等于30岁”,两者逻辑不同,无法替换。

那能不能使用 Teacher::getAge()>=30 呢?

答案是不能。

首先,filter()的参数要么是Lambda表达式,要么是方法引用,不能是方法引用+语句,不伦不类。

其次,也是最重要的,你可以认为Teacher::getAge表示

public Integer getAge(){return this.age;
}

中的return this.age;,它是一个语句。我们可以对表达式叠加判断,比如 a-b ,我们可以继续叠加变成 a-b+c。但是 int d = a-b+c; 已经没办法再叠加了,因为 int d = a-b+c; >= 30 是不可接受的!

处理办法也简单,就是找一个相同逻辑的方法并引用它。假设存在以下方法:

public boolean isBiggerThan30(){return this.age >= 30;
}

那就可以写成:

list.stream().filter(Teacher::isBiggerThan30);

后话

关于方法引用其实还可以展开说,比如可以分为:

  • 静态方法引用(Integer::compare)
  • 实例方法引用(this::getName、user::getName)
  • 构造器方法引用(User::new)

总体来说,方法引用(包括构造器引用)的前提是,函数式接口的方法对应的参数列表和返回值 与 引用类定义的方法的参数列表和返回值 一致。这样说可能比较绕,这里举一个demo:

public class StreamConstructorTest {public static void main(String[] args) {// 下面4个语句都是Person::new,却能赋值给不同的函数式接口// 原因是:每个函数式接口都能从Person类中找到对应的方法(参数列表一致),从而完成方法引用PersonCreatorNoConstruct person1 = Person::new;// 大家可以尝试把Person中Age构造函数注释,那么下面的赋值语句会提示错误,因为此时不存在只有一个age参数的构造器!PersonCreatorWithAge person2 = Person::new;PersonCreatorWithName person3 = Person::new;PersonCreatorAllConstruct person4 = Person::new;}public interface PersonCreatorNoConstruct {// 对应Person无参构造Person create();}public interface PersonCreatorWithAge {// 对应Person的age构造函数Person create(Integer age);}public interface PersonCreatorWithName {// 对应Person的name构造函数Person create(String name);}public interface PersonCreatorAllConstruct {// 对应Person的全参构造函数Person create(Integer age, String name);}@Getter@Setterstatic class Person {private Integer age;private String name;public Person() {}public Person(Integer age) {this.age = age;}public Person(String name) {this.name = name;}public Person(Integer age, String name) {this.age = age;this.name = name;}}
}

但无论是方法引用还是构造器引用,都是细枝末节的东西,本质上学习好Lambda表达式即可。我对方法引用/构造器引用的态度就一个:如果我的代码不是最优,让IDEA提醒我便是,我反正是懒得记~

作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO

进群,大家一起学习,一起进步,一起对抗互联网寒冬

 

http://www.hotlads.com/news/399.html

相关文章:

  • 自学做网站十大搜索引擎排名
  • 网站建设收费标准流程海外广告投放公司
  • wordpress 多用户开启石家庄网站优化
  • 伊利集团网站建设实训nba最新交易一览表
  • 地方门户网站系统分销平台
  • 租房平台网站开发seo诊断的网络问题
  • 怎么备份网站模板怎么查询最新网站
  • 郑州网站建设知名公司西安seo关键词查询
  • 做视频网站要准备哪些资料百度2023免费
  • wordpress添加快速链接seo实战培训课程
  • 北京加盟网站建设导购网站怎么推广
  • 滕州做网站的黑帽seo教程
  • 网站建设方案怎么写腾讯广告投放平台官网
  • 光明网站开发官方百度平台
  • wordpress安装在windows上杭州网站优化效果
  • 网站怎么做才有效果百度网页广告怎么做
  • 江西省城乡建设培训中心网站做一个自己的网站
  • 当今做那些网站能致富各大搜索引擎入口
  • 清江开发公司官网seo人员的相关薪资
  • 做企业平台的网站有哪些内容互动网站建设
  • 贵阳专业做网站公司互动营销的案例有哪些
  • 网站模板怎么用法深圳google推广
  • 深圳网站建设raygf东莞市网站建设
  • 苏州软件开发公司神马seo服务
  • 台州做网站电话网络营销方案设计
  • 做网站模板赚钱游戏代理怎么找渠道
  • 国外设计网站 behance入口中国第三波疫情将在9月份
  • 金融行业做网站深圳百度开户
  • 三合一网站管理系统怎么做的厦门百度关键词优化
  • 网站关于我们示例互联网推广是干什么的