我的Java学习笔记-Lambda表达式

学习目标:

学会使用Lambda表达式及其相关操作


学习内容:

一.什么是Lambda表达式?

1.概念:

Lambda表达式,也可以成为闭包。是Java 8的一个重要新特性。
与匿名类相比,就是匿名方法,是一种把方法作为参数进行传递的编程思想。

2.使用示例:
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);
        }
    }
 
}
3.lambda表达式的重要特征:

(1)可选类型声明:不需要声明参数类型,编译器可以统一识别参数值。

(2)可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号。

(3)可选的大括号:如果主体包含了一个语句,就不需要使用大括号。

(4)可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回了一个数值。

4.使用Lambda表达式的好处:

(1)使代码更简洁
(2)可以装逼

5.不好的地方:

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

(1) 可读性差:与啰嗦的但是清晰的匿名类代码结构比较起来,Lambda表达式一旦变得比较长,就难以理解

(2) 不便于调试:很难在Lambda表达式中增加调试信息,比如日志

(3) 版本支持:Lambda表达式在JDK8版本中才开始支持,如果系统使用的是以前的版本,考虑系统的稳定性等原因,而不愿意升级,那么就无法使用。

二.方法引用

1.引用静态方法:
import java.util.*;
//参考文章末尾的英雄类
import charactor.Hero;

//lambda表达式引用静态方法
public class test3 {
    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)));
        }
        //Comparator<Hero> c = new
        //lambda表达式引用静态方法
        Collections.sort(heros,test3::maxMin);
        System.out.println("按照血量排序后的集合:");
        System.out.println(heros);
    }

    public static int maxMin(Hero h1,Hero h2){
        if(h1.hp>=h2.hp)
            return 1;
        else
            return -1;
    }
}
2.引用对象方法:
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
//参考文章末尾的英雄类
import charactor.Hero;

//lambda表达式引用对象方法
public class test4 {
    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)));
        }
        //Comparator<Hero> c = new
        //lambda表达式引用对象方法
        test4 t4 = new test4();
        Collections.sort(heros,t4::maxMin);
        System.out.println("按照血量排序后的集合:");
        System.out.println(heros);
    }

    public int maxMin(Hero h1,Hero h2){
        if(h1.hp>=h2.hp)
            return 1;
        else
            return -1;
    }
}

3.引用构造器:
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.function.Supplier;
//参考文章末尾的英雄类
import charactor.Hero;

//lambda表达式引用构造器
public class test6 {
    public static void main(String[] args) {
        List<Integer> l;
        l = new ArrayList<>();
        modify(l, "ArrayList");

        l = new LinkedList<>();
        modify(l, "LinkedList");
        
        //lambda表达式引用构造器
        List list1 = getList(ArrayList::new);
        modify(list1, "ArrayList");

    }

    public static List getList(Supplier<List> s) {
        return s.get();
    }

    private static void modify(List<Integer> l, String type) {
        int total = 100 * 1000;
        int index = total / 2;
        final int number = 5;
        //初始化
        for (int i = 0; i < total; i++) {
            l.add(number);
        }

        long start = System.currentTimeMillis();

        for (int i = 0; i < total; i++) {
            int n = l.get(index);
            n++;
            l.set(index, n);
        }
        long end = System.currentTimeMillis();
        System.out.printf("%s总长度是%d,定位到第%d个数据,取出来,加1,再放回去%n 重复%d遍,总共耗时 %d 毫秒 %n", type, total, index, total, end - start);
        System.out.println();
    }
}

三.聚合操作

一.概念:

要了解聚合操作,首先要建立 Stream管道 的概念
*Stream 和Collection结构化的数据不一样,Stream是一系列的元素,就像是生产线上的罐头一样,一串串的出来。
*管道指的是一系列的聚合操作。

管道又分3个部分
*管道源:Collection切换成管道源很简单,调用stream()就行了。数组没有stream()方法,需要使用Arrays.stream(arr) //arr是数组名

*中间操作: 每个中间操作,又会返回一个Stream,比如.filter()又返回一个Stream, 中间操作是“懒”操作,并不会真正进行遍历。

中间操作比较多,主要分两类
对元素进行筛选:
filter 匹配
distinct 去除重复(根据equals判断)
sorted 自然排序
sorted(Comparator) 指定排序
limit 保留
skip 忽略
转换为其他形式的流
mapToDouble 转换为double的流
map 转换为任意类型的流

*结束操作:当这个操作执行后,流就被使用“光”了,无法再被操作。所以这必定是流的最后一个操作。 结束操作不会返回Stream,但是会返回int、float、String、 Collection或者像forEach,什么都不返回, 结束操作才进行真正的遍历行为,在遍历的时候,才会去进行中间操作的相关判断。

常见结束操作如下
forEach() 遍历每个元素
toArray() 转换为数组
min(Comparator) 取最小的元素
max(Comparator) 取最大的元素
count() 总数
findFirst() 第一个元素

: 这个Stream和I/O章节的InputStream,OutputStream是不一样的概念。

二.使用示例:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
//参考文章末尾的英雄类
import charactor.Hero;

/*
首选准备10个Hero对象,hp和damage都是随机数。
分别用传统方式和聚合操作的方式,把hp第三高的英雄名称打印出来
 */
public class test7 {
    public static void main(String[] args) {
        Random random = new Random();
        List<Hero> list = new ArrayList<>();
        for (int i = 0; i < 10; i++) {
            Hero h = new Hero();
            h.name = "hero"+i;
            h.hp = random.nextInt(100);
            h.damage = random.nextInt(500);
            list.add(h);
        }
        /**
         * 我写的
        //聚合遍历集合
        list
                .stream()
                .forEach(h -> System.out.println(h));
        //System.out.println(list);

        //聚合排序
        Object[] heroes = list.stream().sorted((h1, h2)->h1.hp>h2.hp?1:-1).toArray();

        System.out.println(heroes[heroes.length-3]);
        我是个渣渣!*/
        //别人写的的
        String name =list
                .stream()
                .sorted((h1,h2)->h1.hp>h2.hp?-1:1)
                .skip(2)
                .map(h->h.getName())
                .findFirst()
                .get();
        System.out.println(name);
    }

}


学习时间:

三小时

继续奋斗!

另:英雄类

public class Hero{
    public String name;
    public float hp;

    public int 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 Hero(){

    }
    public Hero(String name) {
        this.name =name;
    }

    public boolean matched(){
        return this.hp>100 && this.damage<50;
    }

    public Hero(String name,float hp, int damage) {
        this.name =name;
        this.hp = hp;
        this.damage = damage;
    }

    public int compareHero(Hero h){
        return hp>=h.hp?-1:1;
    }

    public String toString() {
        return "Hero [name=" + name + ", hp=" + hp + ", damage=" + damage + "]\r\n";
    }

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值