https://www.nowcoder.com/tutorial/94/ae05554a3ad84e42b6f9fc4d52859dc4
https://how2j.cn/frontroute
https://how2j.cn/k/lambda/lambda-lamdba-tutorials/697.html
目录
1 引子
lambda 用处:找出某个特征的对象
参见:
https://blog.csdn.net/weixin_40839731/article/details/79594897
1.1 普通方法
用 for 进行逐一判断
1.2 匿名类方式
匿名类:
业务方法代码肯定是有的
就是没有自己名字
HeroChecker checker = new HeroChecker() {
public boolean test(Hero h) {
return (h.hp>100 && h.damage<50);
}
};
完整代码:
package 第17个程序_Lambda.a1_匿名类方式查找;
public class Hero {
String name;
float hp; //血量
float armor; //护甲
int moveSprrd; //速度
public Hero(String name, float hp, float armor){
this.name = name;
this.hp = hp;
this.armor = armor;
}
}
package 第17个程序_Lambda.a1_引子.s1_匿名类方式查找;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
public class test {
public static void main(String[] args) {
Random r = new Random();
List<Hero> list = new LinkedList<>();
for (int i = 0; i < 5; i++)
list.add(new Hero("hero " + r.nextInt(100), r.nextInt(1000), r.nextInt(100)));
print(list);
System.out.println("\n匿名类筛选 hp>100 armor <50 的英雄");
HeroChecker heroChecker = new HeroChecker() {
@Override
public boolean test(Hero hero) {
return (hero.hp > 100 && hero.armor < 50);
}
};
filter(list, heroChecker);
}
public static void filter(List<Hero> list, HeroChecker heroChecker){
int flag = 0;
for (Hero hero: list){
if (heroChecker.test(hero)){
System.out.println(hero.name + " " + hero.hp + " " + hero.armor);
flag++;
}
}
if (flag == 0)
System.out.println("无!");
}
public static void print(List<Hero> list){
System.out.println("输出:");
for (Hero hero:list){
System.out.println(hero.name + " " + hero.hp + " " + hero.armor);
}
}
}
1.3 Lambda
filter(list, hero -> hero.hp>100 && hero.armor<50);
完整代码:
package 第17个程序_Lambda.a1_引子.s2_Lambda;
public class Hero {
String name;
float hp; //血量
float armor; //护甲
int moveSprrd; //速度
public Hero(String name, float hp, float armor){
this.name = name;
this.hp = hp;
this.armor = armor;
}
}
package 第17个程序_Lambda.a1_引子.s2_Lambda;
public interface HeroChecker {
public boolean test(Hero hero);
}
package 第17个程序_Lambda.a1_引子.s2_Lambda;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class test {
public static void main(String[] args) {
Random r = new Random();
List<Hero> list = new ArrayList<>();
for (int i = 0; i < 5; i++){
list.add(new Hero("hero " + i, r.nextInt(1000), r.nextInt(100)));
}
print(list);
System.out.println("用 filter 方式, 查找 hp>100 armor <50 的英雄:");
filter(list, hero -> hero.hp>100 && hero.armor<50);
}
public static void filter(List<Hero> list, HeroChecker heroChecker){
int flag = 0;
for(Hero hero:list){
if(heroChecker.test(hero)){
System.out.println(hero.name + " " + hero.hp + " " + hero.armor);
flag++;
}
}
if (flag == 0)
System.out.println("无!");
}
public static void print(List<Hero> list){
System.out.println("输出:");
for (Hero hero:list){
System.out.println(hero.name + " " + hero.hp + " " + hero.armor);
}
System.out.println();
}
}
1.3.1 弊端
可读性差
不便调试
JDK8 以上支持
1.4 练习
把比较器-Comparator 的代码改为 Lambda 表达式
package 第17个程序_Lambda.a1_引子.s2_Lambda.练习;
public class Hero {
public String name;
public float hp;
public int damage;
public Hero(String name) {
this.name = name;
}
public String toString() {
return "Hero [name=" + name + ", hp=" + hp + ", damage=" + damage + "]\r\n";
}
public Hero(String name, int hp, int damage) {
this.name = name;
this.hp = hp;
this.damage = damage;
}
}
package 第17个程序_Lambda.a1_引子.s2_Lambda.练习;
import java.util.*;
public class test {
public static void main(String[] args) {
Random random = new Random();
List<Hero> heroes = new ArrayList<>();
for (int i = 0; i < 5; i++){
heroes.add(new Hero("hero " + i, random.nextInt(100), random.nextInt(100)) );
}
System.out.println("初始化后: ");
print(heroes);
/*
直接 Collections.sort(heros); 会报错,因为排序标准不知道!
*/
System.out.printf("尝试排序... ");
Collections.sort(heroes, (x,y) -> x.hp>y.hp ? 1:(x.hp == y.hp ? (x.damage>y.damage?1:-1):-1) );
System.out.println("成功!");
print(heroes);
}
public static void print(List<Hero> list){
System.out.println("输出:");
for (Hero hero:list){
System.out.println(hero.name + " " + hero.hp + " " + hero.damage);
}
System.out.println();
}
}
2 方法引用
2.1 引用 静态方法
package 第17个程序_Lambda.a2_方法引用.s1_引用静态方法;
public class Hero {
String name;
float hp; //血量
float armor; //护甲
int moveSprrd; //速度
public Hero(String name, float hp, float armor){
this.name = name;
this.hp = hp;
this.armor = armor;
}
}
package 第17个程序_Lambda.a2_方法引用.s1_引用静态方法;
public interface HeroChecker {
public boolean test(Hero hero);
}
package 第17个程序_Lambda.a2_方法引用.s1_引用静态方法;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class test {
public static void main(String[] args) {
Random r = new Random();
List<Hero> list = new ArrayList<>();
for (int i = 0; i < 5; i++){
list.add(new Hero("hero " + i,r.nextInt(1000), r.nextInt(100)));
}
print(list);
HeroChecker c = new HeroChecker() {
@Override
public boolean test(Hero hero) {
return (hero.hp>100 && hero.armor<50);
}
};
System.out.println("用匿名类过滤");
filter(list,c);
System.out.println("\n用 Lambda 过滤");
filter(list, hero -> (hero.hp>100 && hero.armor<50) );
// 静态方法
System.out.println("\n在 Lambda 中引用静态方法");
filter(list, hero -> (test.testHero(hero)));
System.out.println("\n直接引用静态方法");
filter(list, test::testHero);
}
private static void filter(List<Hero> list, HeroChecker heroChecker){
int flag = 0;
for (Hero hero:list){
if (heroChecker.test(hero)){
System.out.println(hero.name + " " + hero.hp + " " + hero.armor);
flag++;
}
}
if (flag == 0)
System.out.println("无!");
}
public static boolean testHero(Hero hero){
return (hero.hp>100 && hero.armor<50);
}
public static void print(List<Hero> list){
System.out.println("输出:");
for (Hero hero:list){
System.out.println(hero.name + " " + hero.hp + " " + hero.armor);
}
System.out.println();
}
}
2.2 引用 对象方法
TestLambda testLambda = new TestLambda();
filter(heros, testLambda::testHero);
完整代码:
package 第17个程序_Lambda.a2_方法引用.s2_引用对象方法;
public class Hero {
String name;
float hp; //血量
float armor; //护甲
int moveSprrd; //速度
public Hero(String name, float hp, float armor){
this.name = name;
this.hp = hp;
this.armor = armor;
}
}
package 第17个程序_Lambda.a2_方法引用.s2_引用对象方法;
public interface HeroChecker {
public boolean test(Hero hero);
}
package 第17个程序_Lambda.a2_方法引用.s2_引用对象方法;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class test {
public static void main(String[] args) {
Random r = new Random();
List<Hero> list = new ArrayList<>();
for (int i = 0; i < 5; i++){
list.add(new Hero("hero " + i, r.nextInt(1000), r.nextInt(100)));
}
print(list);
System.out.println("引用对象方法过滤结果:");
test t = new test();
filter(list, test::testHero);
}
public static boolean testHero(Hero hero){
return (hero.hp>100 && hero.armor<50);
}
private static void filter(List<Hero> list, HeroChecker heroChecker){
int flag = 0;
for (Hero hero: list){
if (heroChecker.test(hero)){
System.out.printf(hero.name + " " + hero.hp + " " + hero.armor + " \t");
flag++;
}
}
if (flag == 0)
System.out.println("无!");
}
public static void print(List<Hero> list){
System.out.println("输出:");
for (Hero hero:list){
System.out.printf(hero.name + " " + hero.hp + " " + hero.armor + " \t");
}
System.out.println();
}
}
2.3 引用 容器中的对象方法
Hero 中加方法:
public boolean matched(){
return this.hp>100 && this.damage<50;
}
Lambda 表达式:
filter(heros,h-> h.hp>100 && h.damage<50 );
=filter(heros,h-> h.matched() );
= filter(heros, Hero::matched);
完整代码::
package 第17个程序_Lambda.a2_方法引用.s3_引用容器中对象的方法;
public class Hero {
String name;
float hp; //血量
float armor; //护甲
int moveSprrd; //速度
public Hero(String name, float hp, float armor){
this.name = name;
this.hp = hp;
this.armor = armor;
}
public boolean matched(){
return (this.hp>100 && this.armor<50);
}
}
package 第17个程序_Lambda.a2_方法引用.s3_引用容器中对象的方法;
public interface HeroChecker {
public boolean test(Hero hero);
}
package 第17个程序_Lambda.a2_方法引用.s3_引用容器中对象的方法;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class test {
public static void main(String[] args) {
Random r = new Random();
List<Hero> list = new ArrayList<>();
for (int i = 0; i < 5; i++){
list.add(new Hero("hero " + i, r.nextInt(1000), r.nextInt(100)));
}
print(list);
// System.out.println("Lambda 表达式过滤:");
// filter(list, hero -> (hero.hp>100 && hero.armor<50) );
// System.out.println("Lambda 调用容器中 对象的 matched 过滤:");
// filter(list, hero -> hero.matched());
System.out.println("引用容器中对象的方法 过滤结果");
filter(list, Hero::matched);
}
private static void filter(List<Hero> list, HeroChecker heroChecker){
int flag = 0;
for (Hero hero: list){
if (heroChecker.test(hero)){
System.out.printf(hero.name + " " + hero.hp + " " + hero.armor + " \t");
flag++;
}
}
if (flag == 0)
System.out.println("无!");
}
public static void print(List<Hero> list){
System.out.println("输出:");
for (Hero hero:list){
System.out.printf(hero.name + " " + hero.hp + " " + hero.armor + " \t");
}
System.out.println();
}
}
2.4 引用 构造器
package 第17个程序_Lambda.a2_方法引用.s4_引用构造器;
public interface Supplier<T> {
T get();
}
package 第17个程序_Lambda.a2_方法引用.s4_引用构造器;
import java.util.ArrayList;
import java.util.List;
public class test {
public static void main(String[] args) {
Supplier<List> supplier = new Supplier<List>() {
@Override
public List get() {
return new ArrayList();
}
};
// 匿名类
List list1 = getList(supplier);
//Lambda 表达式
List list2 = getList( () -> new ArrayList());
// 引用构造器
List list3 = getList( ArrayList::new );
}
public static List getList(Supplier<List> supplier){
return supplier.get();
}
}
2.5 练习1
比较器 - Comparator 代码
【引用静态方法】实现
【引用容器中的对象方法】实现
package 第17个程序_Lambda.a2_方法引用.练习1;
public class Hero {
public String name;
public float hp;
public int damage;
public Hero(String name) {
this.name = name;
}
public String toString() {
return "Hero [name=" + name + ", hp=" + hp + ", damage=" + damage + "]\r\n";
}
public Hero(String name, int hp, int damage) {
this.name = name;
this.hp = hp;
this.damage = damage;
}
public static int matched(Hero hero1, Hero hero2){
return (hero1.hp>hero2.hp ? 1:-1);
}
}
package 第17个程序_Lambda.a2_方法引用.s3_引用容器中对象的方法;
public interface HeroChecker {
public boolean test(Hero hero);
}
package 第17个程序_Lambda.a2_方法引用.练习1;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class test {
public static void main(String[] args) {
Random random = new Random();
List<Hero> heroes = new ArrayList<>();
for (int i = 0; i < 5; i++){
heroes.add(new Hero("hero " + i, random.nextInt(1000), random.nextInt(100)) );
}
System.out.println("初始化后: ");
System.out.println(heroes);
// System.out.println("尝试排序... ");
// System.out.println("Lambda 引用静态方法");
// Collections.sort(heroes, (hero1, hero2) -> (test.compare(hero1, hero2)) );
// System.out.println("成功!");
// System.out.println(heroes);
// System.out.println("直接引用静态方法");
// Collections.sort(heroes, test::compare);
// System.out.println("成功!");
// System.out.println(heroes);
System.out.println("引用容器中对象方法:");
Collections.sort(heroes, Hero::matched);
System.out.println(heroes);
}
public static int compare(Hero hero1, Hero hero2){
return hero1.hp>hero2.hp ? 1:-1;
}
}
2.6 练习2
见下面代码,将其改成构造器模式
原:
List<Integer> l;
l = new ArrayList<>();
insertFirst(l, "ArrayList");
l = new LinkedList<>();
insertFirst(l, "LinkedList");
目标:
insertFirst(ArrayList::new, "ArrayList");
insertFirst(LinkedList::new, "LinkedList");
原代码:
package 第17个程序_Lambda.a2_方法引用.练习2;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class src {
public static void main(String[] args) {
List<Integer> l;
l = new ArrayList<>();
insertFirst(l, "ArrayList");
l = new LinkedList<>();
insertFirst(l, "LinkedList");
}
private static void insertFirst(List<Integer> l, String type) {
int total = 1000 * 100;
final int number = 5;
long start = System.currentTimeMillis();
for (int i = 0; i < total; i++) {
l.add(0, number);
}
long end = System.currentTimeMillis();
System.out.printf("在%s 最前面插入%d条数据,总共耗时 %d 毫秒 %n", type, total, end - start);
}
}
答案:
package 第17个程序_Lambda.a2_方法引用.练习2;
public interface Supplier<T> {
T get();
}
package 第17个程序_Lambda.a2_方法引用.练习2;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class test {
public static void main(String[] args) {
List<Integer> l;
l = new ArrayList<>();
insertFirst(ArrayList::new, "ArrayList");
l = new LinkedList<>();
insertFirst(LinkedList::new, "LinkedList");
}
private static void insertFirst(Supplier<List> supplier , String type) {
int total = 1000 * 100;
final int number = 5;
long start = System.currentTimeMillis();
List list = supplier.get();
for (int i = 0; i < total; i++) {
list.add(0, number);
}
long end = System.currentTimeMillis();
System.out.printf("在%s 最前面插入%d条数据,总共耗时 %d 毫秒 %n", type, total, end - start);
}
}
3 聚合操作
传统方法:
for (Hero h : heros) {
if (h.hp > 100 && h.damage < 50)
System.out.println(h.name);
}
聚合:
heros
.stream()
.filter(h -> h.hp > 100 && h.damage < 50)
.forEach(h -> System.out.println(h.name));
3.1 简单程序
管道源是 集合 和 数组
对应操作不同
package 第17个程序_Lambda.a3_聚合操作.s1_简单程序;
public class Hero {
String name;
float hp; //血量
float armor; //护甲
int moveSprrd; //速度
public Hero(String name, float hp, float armor){
this.name = name;
this.hp = hp;
this.armor = armor;
}
public String toString() {
return "Hero [name=" + name + ", hp=" + hp + ", damage=" + armor + "]\r";
}
}
package 第17个程序_Lambda.a3_聚合操作.s1_简单程序;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
public class test {
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("输出:");
for (Hero h : heros){
System.out.println("Hero [name=" + h.name + ", hp=" + h.hp + ", damage=" + h.armor + "]\r");
}
// 管道源是集合
System.out.println("\n管道源是集合");
heros
.stream()
.forEach(hero -> System.out.println(hero) );
// 管道源是数组
System.out.println("\n管道源是数组");
Hero[] heroes1 = heros.toArray(new Hero[heros.size()]);
Arrays
.stream(heroes1)
.forEach(hero -> System.out.println(hero));
}
}
3.2 中间操作
对元素进行筛选:
filter 匹配
distinct 去除重复(根据equals判断)
sorted 自然排序
sorted(Comparator) 指定排序
limit 保留
skip 忽略
package 第17个程序_Lambda.a3_聚合操作.s2_中间操作;
public class Hero implements Comparable<Hero>{
public String name;
public float hp;
public int damage;
public Hero(){}
public Hero(String name, float hp, int damage){
this.name = name;
this.hp = hp;
this.damage = damage;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public float getHp(){
return hp;
}
public void setHp(float hp){
this.hp = hp;
}
public int getDamage(){
return damage;
}
public void setDamage(int damage){
this.damage = damage;
}
public String toString(){
return "Hero [ name = " + name + ", hp = " + hp + ", damage = " + damage + " ]" ;
}
@Override
public int compareTo(Hero o) {
if (o.damage > damage)
return 1;
else
return -1;
}
}
package 第17个程序_Lambda.a3_聚合操作.s2_中间操作;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class test {
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)));
}
heros.add(heros.get(0));// 首末元素重复,故意
for (Hero h : heros){
System.out.println("Hero [ name = " + h.name + ", hp = " + h.hp + ", damage = " + h.damage + " ]");
}
System.out.println("\nhp>100 && damage<50 的数据:");
heros
.stream()
.filter(hero -> (hero.hp>100 && hero.damage<50) )
.forEach(hero -> System.out.println(hero.toString()) );
System.out.println("\n去除重复的数据:");
heros
.stream()
.distinct()
.forEach(hero -> System.out.println(hero.toString()) );
System.out.println("\n按血量排序:");
heros
.stream()
.sorted( (hero1, hero2) -> hero1.hp > hero2.hp ? 1:-1 )
.forEach(hero -> System.out.println(hero.toString()) );
System.out.println("\n保留前3个:");
heros
.stream()
.limit(3)
.forEach(hero -> System.out.println(hero.toString()) );
System.out.println("\n忽略前3个:");
heros
.stream()
.skip(3)
.forEach(hero -> System.out.println(hero.toString()) );
System.out.println("\n转为 double 的 Stream");
heros
.stream()
.mapToDouble(Hero::getHp)
.forEach(hero -> System.out.println(hero) );
System.out.println("\n转为任意类型的 Stream");
heros
.stream()
.map( hero -> hero.name + " - " + hero.hp + " - " + hero.damage)
.forEach(hero -> System.out.println(hero) );
}
}
3.3 结束操作
forEach() 遍历每个元素
toArray() 转换为数组
min(Comparator) 取最小的元素
max(Comparator) 取最大的元素
count() 总数
findFirst() 第一个元素
package 第17个程序_Lambda.a3_聚合操作.s3_结束操作;
public class Hero implements Comparable<Hero>{
public String name;
public float hp;
public int damage;
public Hero(){}
public Hero(String name, float hp, int damage){
this.name = name;
this.hp = hp;
this.damage = damage;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public float getHp(){
return hp;
}
public void setHp(float hp){
this.hp = hp;
}
public int getDamage(){
return damage;
}
public void setDamage(int damage){
this.damage = damage;
}
public String toString(){
return "Hero [ name = " + name + ", hp = " + hp + ", damage = " + damage + " ]" ;
}
@Override
public int compareTo(Hero o) {
if (o.damage > damage)
return 1;
else
return -1;
}
}
package 第17个程序_Lambda.a3_聚合操作.s3_结束操作;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class test {
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("遍历每一个元素:");
heros
.stream()
.forEach(hero -> System.out.println(hero.toString()) );
System.out.println("\n返回数组:");
Object[] hs = heros
.stream()
.toArray();
System.out.println(hs.toString());
System.out.println("\n返回伤害最低的英雄:");
Hero minDamage = heros
.stream()
.min( (hero1, hero2)->hero1.damage - hero2.damage )
.get();
System.out.println(minDamage.toString());
System.out.println("\n返回伤害最高的英雄:");
Hero maxDamage = heros
.stream()
.max( (hero1, hero2)->hero1.damage - hero2.damage )
.get();
System.out.println(maxDamage.toString());
System.out.println("\n流中数据总数:");
long count = heros
.stream()
.count();
System.out.println(count + "个");
System.out.println("\n第一个英雄:");
Hero firstHero = heros
.stream()
.findFirst()
.get();
System.out.println(firstHero.toString());
}
}
3.4 练习
准备 10 个随机 Hero
用 传统方式、聚合操作,把 hp 第 3 高的英雄名称打印出来
package 第17个程序_Lambda.a3_聚合操作.练习;
public class Hero implements Comparable<Hero>{
public String name;
public float hp;
public int damage;
public Hero(){}
public Hero(String name, float hp, int damage){
this.name = name;
this.hp = hp;
this.damage = damage;
}
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
public float getHp(){
return hp;
}
public void setHp(float hp){
this.hp = hp;
}
public int getDamage(){
return damage;
}
public void setDamage(int damage){
this.damage = damage;
}
public String toString(){
return "Hero [ name = " + name + ", hp = " + hp + ", damage = " + damage + " ]" ;
}
@Override
public int compareTo(Hero o) {
if (o.damage > damage)
return 1;
else
return -1;
}
}
package 第17个程序_Lambda.a3_聚合操作.练习;
import 第17个程序_Lambda.a3_聚合操作.s3_结束操作.Hero;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class test {
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)));
}
heros.add(heros.get(0));// 故意加一个重复的元素
System.out.println("传统方式找第3高hp:");
Collections.sort(heros, (hero1, hero2)->hero1.hp>hero2.hp?-1:1 );// 降序
System.out.println(heros.get(2).toString());
System.out.println("\n去重遍历:");
heros
.stream()
.distinct()
.sorted((hero1, hero2)->hero1.hp>hero2.hp?-1:1)
.forEach(hero -> System.out.println("Hero [ name = " + hero.name + ", hp = " + hero.hp + ", damage = " + hero.damage + " ]"));
System.out.println("\n聚合方式找第3高的hp:");
Hero hero3 = heros
.stream()
.sorted((hero1, hero2)->hero1.hp>hero2.hp?-1:+1)
.skip(2) // 忽略前7个...
.findFirst()
.get();
System.out.println(hero3.toString());
}
}