how2j.cn


工具版本兼容问题
假设一个情景: 找出满足条件的Hero
本教程将从使用普通方法匿名类,以及Lambda这几种方式,逐渐的引入Lambda的概念


本视频是解读性视频,所以希望您已经看过了本知识点的内容,并且编写了相应的代码之后,带着疑问来观看,这样收获才多。 不建议一开始就观看视频



20分39秒
本视频采用html5方式播放,如无法正常播放,请将浏览器升级至最新版本,推荐火狐,chrome,360浏览器。 如果装有迅雷,播放视频呈现直接下载状态,请调整 迅雷系统设置-基本设置-启动-监视全部浏览器 (去掉这个选项)。 chrome 的 视频下载插件会影响播放,如 IDM 等,请关闭或者切换其他浏览器



步骤 1 : 普通方法   
步骤 2 : 匿名类方式   
步骤 3 : Lambda方式   
步骤 4 : 设置eclipse以支持Lambda   
步骤 5 : 从匿名类演变成Lambda表达式   
步骤 6 : 匿名方法   
步骤 7 : Lambda的弊端   
步骤 8 : 练习-Comparator   
步骤 9 : 答案-Comparator   

使用一个普通方法,在for循环遍历中进行条件判断,筛选出满足条件的数据

hp>100 && damage<50
普通方法
package lambda; import java.util.ArrayList; import java.util.List; import java.util.Random; import charactor.Hero; public class TestLambda { public static void main(String[] args) { Random r = new Random(); List<Hero> heros = new ArrayList<Hero>(); for (int i = 0; i < 10; i++) { heros.add(new Hero("hero " + i, r.nextInt(1000), r.nextInt(100))); } System.out.println("初始化后的集合:"); System.out.println(heros); System.out.println("筛选出 hp>100 && damange<50的英雄"); filter(heros); } private static void filter(List<Hero> heros) { for (Hero hero : heros) { if(hero.hp>100 && hero.damage<50) System.out.print(hero); } } }
package charactor; public class Hero implements Comparable<Hero>{ public String name; public float hp; public int damage; public Hero(){ } public Hero(String name) { this.name =name; } //初始化name,hp,damage的构造方法 public Hero(String name,float hp, int damage) { this.name =name; this.hp = hp; this.damage = damage; } @Override public int compareTo(Hero anotherHero) { if(damage<anotherHero.damage) return 1; else return -1; } @Override public String toString() { return "Hero [name=" + name + ", hp=" + hp + ", damage=" + damage + "]\r\n"; } }
首先准备一个接口HeroChecker,提供一个test(Hero)方法
然后通过匿名类的方式,实现这个接口

HeroChecker checker = new HeroChecker() {
public boolean test(Hero h) {
return (h.hp>100 && h.damage<50);
}
};

接着调用filter,传递这个checker进去进行判断,这种方式就很像通过Collections.sort在对一个Hero集合排序,需要传一个Comparator的匿名类对象进去一样。

匿名类方式
package lambda; import java.util.ArrayList; import java.util.List; import java.util.Random; import charactor.Hero; public class TestLambda { public static void main(String[] args) { Random r = new Random(); List<Hero> heros = new ArrayList<Hero>(); for (int i = 0; i < 5; i++) { heros.add(new Hero("hero " + i, r.nextInt(1000), r.nextInt(100))); } System.out.println("初始化后的集合:"); System.out.println(heros); System.out.println("使用匿名类的方式,筛选出 hp>100 && damange<50的英雄"); HeroChecker checker = new HeroChecker() { @Override public boolean test(Hero h) { return (h.hp>100 && h.damage<50); } }; filter(heros,checker); } private static void filter(List<Hero> heros,HeroChecker checker) { for (Hero hero : heros) { if(checker.test(hero)) System.out.print(hero); } } }
package lambda; import charactor.Hero; public interface HeroChecker { public boolean test(Hero h); }
使用Lambda方式筛选出数据

filter(heros,(h)->h.hp>100 && h.damage<50);

同样是调用filter方法,从上一步的传递匿名类对象,变成了传递一个Lambda表达式进去

h->h.hp>100 && h.damage<50


咋一看Lambda表达式似乎不好理解,其实很简单,下一步讲解如何从一个匿名类一点点演变成Lambda表达式
Lambda方式
package lambda; import java.util.ArrayList; import java.util.List; import java.util.Random; import charactor.Hero; public class TestLamdba { public static void main(String[] args) { Random r = new Random(); List<Hero> heros = new ArrayList<Hero>(); for (int i = 0; i < 5; i++) { heros.add(new Hero("hero " + i, r.nextInt(1000), r.nextInt(100))); } System.out.println("初始化后的集合:"); System.out.println(heros); System.out.println("使用Lamdba的方式,筛选出 hp>100 && damange<50的英雄"); filter(heros,h->h.hp>100 && h.damage<50); } private static void filter(List<Hero> heros,HeroChecker checker) { for (Hero hero : heros) { if(checker.test(hero)) System.out.print(hero); } } }
步骤 4 :

设置eclipse以支持Lambda

edit
如果你的eclipse能够正常识别Lambda,那么就可以跳过这个章节了。
因为Lambda是JDK8的内容,除了JDK需要使用1.8以上版本外(在JDK环境变量配置下载的就是1.8了),还需要在eclipse中把编译器设置为1.8才能够正常识别Lambda.

设置办法:
菜单->Window->Preferences->Java-Compiler->Compiler compliance leve: 设置为1.8即可
设置eclipse以支持Lambda
步骤 5 :

从匿名类演变成Lambda表达式

edit
Lambda表达式可以看成是匿名类一点点演变过来
1. 匿名类的正常写法

HeroChecker c1 = new HeroChecker() {
public boolean test(Hero h) {
return (h.hp>100 && h.damage<50);
}
};

2. 把外面的壳子去掉
只保留方法参数方法体
参数和方法体之间加上符号 ->

HeroChecker c2 = (Hero h) ->{
return h.hp>100 && h.damage<50;
};


3. 把return和{}去掉

HeroChecker c3 = (Hero h) ->h.hp>100 && h.damage<50;


4. 把 参数类型和圆括号去掉(只有一个参数的时候,才可以去掉圆括号)

HeroChecker c4 = h ->h.hp>100 && h.damage<50;


5. 把c4作为参数传递进去

filter(heros,c4);


6. 直接把表达式传递进去

filter(heros, h -> h.hp > 100 && h.damage < 50);
package lambda; import java.util.ArrayList; import java.util.List; import java.util.Random; import charactor.Hero; public class TestLamdba { public static void main(String[] args) { Random r = new Random(); List<Hero> heros = new ArrayList<Hero>(); for (int i = 0; i < 5; i++) { heros.add(new Hero("hero " + i, r.nextInt(1000), r.nextInt(100))); } System.out.println("初始化后的集合:"); System.out.println(heros); System.out.println("使用匿名类的方式,筛选出 hp>100 && damange<50的英雄"); // 匿名类的正常写法 HeroChecker c1 = new HeroChecker() { @Override public boolean test(Hero h) { return (h.hp > 100 && h.damage < 50); } }; // 把new HeroChcekcer,方法名,方法返回类型信息去掉 // 只保留方法参数和方法体 // 参数和方法体之间加上符号 -> HeroChecker c2 = (Hero h) -> { return h.hp > 100 && h.damage < 50; }; // 把return和{}去掉 HeroChecker c3 = (Hero h) -> h.hp > 100 && h.damage < 50; // 把 参数类型和圆括号去掉 HeroChecker c4 = h -> h.hp > 100 && h.damage < 50; // 把c4作为参数传递进去 filter(heros, c4); // 直接把表达式传递进去 filter(heros, h -> h.hp > 100 && h.damage < 50); } private static void filter(List<Hero> heros, HeroChecker checker) { for (Hero hero : heros) { if (checker.test(hero)) System.out.print(hero); } } }
匿名类 概念相比较,
Lambda 其实就是匿名方法,这是一种把方法作为参数进行传递的编程思想。

虽然代码是这么写

filter(heros, h -> h.hp > 100 && h.damage < 50);

但是,Java会在背后,悄悄的,把这些都还原成匿名类方式
引入Lambda表达式,会使得代码更加紧凑,而不是各种接口和匿名类到处飞。
Lambda表达式虽然带来了代码的简洁,但是也有其局限性。
1. 可读性差,与啰嗦的但是清晰的匿名类代码结构比较起来,Lambda表达式一旦变得比较长,就难以理解
2. 不便于调试,很难在Lambda表达式中增加调试信息,比如日志
3. 版本支持,Lambda表达式在JDK8版本中才开始支持,如果系统使用的是以前的版本,考虑系统的稳定性等原因,而不愿意升级,那么就无法使用。

Lambda比较适合用在简短的业务代码中,并不适合用在复杂的系统中,会加大维护成本。
步骤 8 :

练习-Comparator

edit  姿势不对,事倍功半! 点击查看做练习的正确姿势
比较器-Comparator 章节中的代码,按照从匿名类演变成Lambda表达式的步骤,改写为Lambda表达式
步骤 9 :

答案-Comparator

edit
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
在查看答案前,尽量先自己完成,碰到问题再来查看答案,收获会更多
查看本答案会花费4个积分,您目前总共有点积分。查看相同答案不会花费额外积分。 积分增加办法 或者一次性购买JAVA 中级总计0个答案 (总共需要0积分)
查看本答案会花费4个积分,您目前总共有点积分。查看相同答案不会花费额外积分。 积分增加办法 或者一次性购买JAVA 中级总计0个答案 (总共需要0积分)
账号未激活 账号未激活,功能受限。 请点击激活
本视频是解读性视频,所以希望您已经看过了本答案的内容,带着疑问来观看,这样收获才多。 不建议一开始就观看视频

4分10秒 本视频采用html5方式播放,如无法正常播放,请将浏览器升级至最新版本,推荐火狐,chrome,360浏览器。 如果装有迅雷,播放视频呈现直接下载状态,请调整 迅雷系统设置-基本设置-启动-监视全部浏览器 (去掉这个选项)。 chrome 的 视频下载插件会影响播放,如 IDM 等,请关闭或者切换其他浏览器


package collection; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Random; import charactor.Hero; public class TestCollection { public static void main(String[] args) { Random r =new Random(); List<Hero> heros = new ArrayList<Hero>(); for (int i = 0; i < 10; i++) { heros.add(new Hero("hero "+ i, r.nextInt(100), r.nextInt(100))); } System.out.println("初始化后的集合:"); System.out.println(heros); //匿名类 Comparator<Hero> c = new Comparator<Hero>() { @Override public int compare(Hero h1, Hero h2) { return h1.hp>=h2.hp?1:-1; } }; //Lambda表达式 c = (Hero h1, Hero h2)-> { return h1.hp>=h2.hp?1:-1; }; //去掉 return和大括号 c = (Hero h1, Hero h2)->h1.hp>=h2.hp?1:-1; //去掉 参数类型 c = (h1, h2)->h1.hp>=h2.hp?1:-1; //有两个参数,无法去掉圆括号 Collections.sort(heros,c); //直接把Lambda表达式作为参数传进去 Collections.sort(heros,(h1, h2)->h1.hp>=h2.hp?1:-1); System.out.println(heros); } }


HOW2J公众号,关注后实时获知最新的教程和优惠活动,谢谢。


问答区域    
2024-07-12 使用 Lambda 创建匿名类实现Collection排序排序
虚心求学




[Hero0,969,179][Hero1,614,545][Hero2,632,895] 排序前 [[Hero0,969,179], [Hero1,614,545], [Hero2,632,895]] 排序后 [[Hero0,969,179], [Hero2,632,895], [Hero1,614,545]]
public static void main(String[] args) {
		List<Hero> hs = getHeros(3);
		System.out.println("排序前");
		System.out.println(hs);
		System.out.println("排序后");
		
		Collections.sort(hs,(o1, o2) ->{
				if (o1.hp > o2.hp)
					return -1;
				else if (o1.hp == o2.hp)
					return 0;
				else
					return 1;
			}
		);
		System.out.println(hs);
	}

	public static List<Hero> getHeros(int num) {
		Random r = new Random();
		List<Hero> heroes = new ArrayList<>();
		for (int i = 0; i < num; i++) {
			Hero h = new Hero("Hero" + i, r.nextInt(1000), r.nextInt(1000));
			heroes.add(h);
			System.out.print(h);
		}
		System.out.println();
		System.out.println();
		return heroes;
	}

							





回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到





2022-08-02 为什么没有用到implements HeroChecker
达拉崩吧班德贝迪布鲁翁

为什么这里没有implements接口HeroChecker




3 个答案

木宇
答案时间:2024-07-12
1

实习英雄
答案时间:2023-12-25
import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Random; import charactor.Hero; public class testcollection { public static void main(String[] args) { Random r =new Random(); List<Hero> heros = new ArrayList<Hero>(); for (int i = 0; i < 10; i++) { //通过随机值实例化hero的hp和damage heros.add(new Hero("hero "+ i, r.nextInt(100), r.nextInt(100))); } System.out.println("初始化后的集合:"); System.out.println(heros); //直接调用sort会出现编译错误,因为Hero有各种属性 //到底按照哪种属性进行比较,Collections也不知道,不确定,所以没法排 //Collections.sort(heros); //引入Comparator,指定比较的算法 // Comparator<Hero> c = new Comparator<Hero>() { // @Override // public int compare(Hero h1, Hero h2) { // //按照hp进行排序 // if(h1.hp>=h2.hp) // return 1; //正数表示h1比h2要大 // else // return -1; // } // }; // Collections.sort(heros, (Hero h1, Hero h2) -> Integer.compare(h1.hp, h2.hp)); Comparator<Hero> c = (h1,h2) -> Integer.compare(h1.hp, h2.hp); Collections.sort(heros, c); System.out.println("按照血量排序后的集合:"); System.out.println(heros); } }

烦恼风
答案时间:2023-02-09
匿名内部类没有类名就没得implements了,如果是普通内部类就要implements



回答已经提交成功,正在审核。 请于 我的回答 处查看回答记录,谢谢
答案 或者 代码至少填写一项, 如果是自己有问题,请重新提问,否则站长有可能看不到




2022-06-20 答案
2021-08-17 答案
2021-07-25 练习 - Comparator


提问太多,页面渲染太慢,为了加快渲染速度,本页最多只显示几条提问。还有 22 条以前的提问,请 点击查看

提问之前请登陆
提问已经提交成功,正在审核。 请于 我的提问 处查看提问记录,谢谢
关于 JAVA 中级-Lambda-Hello Lambda 的提问

尽量提供截图代码异常信息,有助于分析和解决问题。 也可进本站QQ群交流: 578362961
提问尽量提供完整的代码,环境描述,越是有利于问题的重现,您的问题越能更快得到解答。
对教程中代码有疑问,请提供是哪个步骤,哪一行有疑问,这样便于快速定位问题,提高问题得到解答的速度
在已经存在的几千个提问里,有相当大的比例,是因为使用了和站长不同版本的开发环境导致的,比如 jdk, eclpise, idea, mysql,tomcat 等等软件的版本不一致。
请使用和站长一样的版本,可以节约自己大量的学习时间。 站长把教学中用的软件版本整理了,都统一放在了这里, 方便大家下载: https://how2j.cn/k/helloworld/helloworld-version/1718.html

上传截图