• Lambda表达式常见用法


    Lambda介绍

    Lambda,别名函数式编程

    函数式编程是一种编程范式。它把计算当成是数学函数的求值,从而避免改变状态和使用可变数据。它是一种声明式的编程范式,通过表达式和声明而不是语句来编程。

    Lambda表达式的优缺点

    优点:

    1. 代码简洁,开发迅速,方便函数式编程
    2. 非常容易进行并行计算,尤其适用于遍历结果,循环计算数值或者赋值时
    3. 结合 hashmap 的 computeIfAbsent 方法,递归运算非常快。java有针对递归的专门优化。
    4. 减少匿名内部类的创建,节省资源(匿名内部类会产生一个class文件,而Lambda不会产生class文件,所以在类加载时,Lambda表达式的效率更高。)

    缺点:

    1. 代码可读性变差,不容易进行调试
    2. 不易于后期维护,必须熟悉lambda表达式和抽象函数中参数的类型
    3. 不能再foreach中修改forEach外面的值,强制类型转换不方便(一定要搞清楚到底是 map 还是 mapToDouble 还是 mapToInt)
    4. 性能方面,如果不并行计算,很多计算未必有传统的for性能要高(并行计算有时需要预热才显示出效率优势)

    符号表示

    lambda是一个匿名函数
    
    () 里的表示参数
    // 括号中的参数只有一个,()可以省略
    // 括号中的参数列表的数据类型,可以省略不写(编译器自己会根据上下文语境推断出类型的)
    
    {} 里的表示方法体
    // Lambda体只有一句语句({ 只有一句语句 }),无论是否有返回值,都可以省略({ }, return , 分号 )
    // 注意:在省略{ }的同时要(return)和分号一起省略
    
    -> 表示lambda运算符
    

    简单运用示例

    匿名内部类调用

    函数式接口:只有一个方法的接口。只要是函数式接口,都可以通过匿名函数来实现。

    public class Test {
        interface Demo{
            int method(String s);
        }
        public static void main(String[] args) {
    
            // 匿名内部类调用
            Demo demo = new Demo() {
                @Override
                public int method(String s) {
                    return Integer.parseInt(s);
                }
            };
            int v = demo.method("111");
    
            // lambda表达式
            Demo demo2 = (s) -> {
                return Integer.parseInt(s);
            };
            int v2 = demo2.method("222");
    
            // 单行简写
            Demo demo3 = s -> Integer.parseInt(s);
            int v3 = demo3.method("333");
        }
    }
    

    并行计算求和

    public class Demo {
        public static void main(String[] args) {
            List<String> values = Arrays.asList("1","2","3","4");
            System.out.println(sum(values));
        }
        public static int sum(List<String> values){
           // mapToInt方法返回的是一个int的Stream,再次调用stream.sum()得到和
           return values.parallelStream().mapToInt(i -> Integer.parseInt(i)).sum();
        }
    }
    

    ArryList排序

    public class Test1 {
    
        public static void main(String[] args) {
            /**
             * 需求:
             * 已知在ArryList中有若干个Person类对象,将这些Person对象按照年龄来降序排序
             */
            List<Person> list = new ArrayList<>();
            list.add(new Person("小蓝",10));
            list.add(new Person("小红",11));
            list.add(new Person("小紫",18));
            list.add(new Person("小橙",20));
    
            //在sort方法中,o1是最后面的元素,o2是倒数第二个元素,以此类推,流是处理元素是从后面开始取值。
            list.sort((o1,o2) -> o2.age - o1.age);
        }
    }
    

    TreeSet排序

    public class Test2 {
        public static void main(String[] args) {
            // 使用Lambda表达式来实现Comparator接口,并实例化一个TreeSet对象
            TreeSet<Person> set = new TreeSet<>((o1,o2) -> {
                if(o1.age >= o2.age){
                    return -1;
                }else {
                    return 1;
                }
            });
            set.add(new Person("小蓝",10));
            set.add(new Person("小红",11));
            set.add(new Person("小紫",18));
            set.add(new Person("小橙",20));
            System.out.println(set);
        }
    }
    

    forEach遍历输出

    public class Test3 {
        public static void main(String[] args) {
            //集合的遍历
            ArrayList<Integer> list = new ArrayList<>();
            //添加元素
            Collections.addAll(list,1,2,3,4,5,6,7,8,9);
            for (Integer integer : list) {
                System.out.println(integer);
            }
            //将集合中的每一个元素带入到方法accept中
            list.forEach(System.out::println);
    
            //还可以用forEach方法输出集合中的偶数
            list.forEach(elm -> {
                if(elm %2 == 0){
                    System.out.println(elm);
                }
            });
        }
    }
    

    removeIf删除方法

    public class Test4 {
        public static void main(String[] args) {
            List<Person> list = new ArrayList<>();
            list.add(new Person("小蓝",10));
            list.add(new Person("小红",11));
            list.add(new Person("小紫",10));
            list.add(new Person("小橙",20));
    
            //之前删除年龄大于10岁的元素  使用迭代器删除
            ListIterator<Person> it = list.listIterator();
            while (it.hasNext()){
                Person person = it.next();
                if (person.age > 10){
                    it.remove();
                }
            }
            //使用lambda实现
            //将集合中的每一个元素都带入到test方法中,如果返回值是true将删除
            list.removeIf(t -> {
                if (t.age > 10){
                    return true;
                }else {
                    return false;
                }
            });
            //简化
            list.removeIf(t -> t.age>10);
            System.out.println(list);
        }
    }
    

    开辟线程

    public class Test5 {
        public static void main(String[] args) {
            //使用lambda表达式开辟一个线程,做一个数字的输出
            Thread t = new Thread(() -> {
                for (int i =0; i<10; i++){
                    System.out.println(i);
                }
            });
            t.start();
        }
    }
    

    Stream的使用

    Stream流的filter使用

    List<String> list = Arrays.asList("张三", "李四", "王五", "小六");
    
    List<String> result = list.stream().filter(str -> !"李四".equals(str)).collect(Collectors.toList());
    System.out.println("stream 过滤之后:" + result);
    
    String result2 = list.stream().filter(str -> "李四".equals(str)).findAny().orElse("找不到!");
    System.out.println("stream 过滤之后 2:" + result2);
    

    Stream流的map使用

    // 示例一:转换大写
    List<String> list1 = Arrays.asList("zhangSan", "liSi", "wangWu");
    
    List<String> list11 = list1.stream().map(String::toUpperCase).collect(Collectors.toList());
    System.out.println("转换之后的数据:" + list11);
    
    // 示例二:转换数据类型
    List<String> list2 = Arrays.asList("1", "2", "3");
    
    List<Integer> list22 = list2.stream().map(Integer::valueOf).collect(Collectors.toList());
    System.out.println("转换之后的数据:" + list22);
    
    // 示例三:获取平方
    List<Integer> list3 = Arrays.asList(new Integer[] { 1, 2, 3, 4, 5 });
    List<Integer> list33 = list3.stream().map(n -> n * n).collect(Collectors.toList());
    System.out.println("平方的数据:" + list33);
    
    // 示例四:list对象转list对象
    // 将List<User>对象中的name属性转换为List<String>对象
    List<String> listStr= user.stream().map(x -> x.getName()).collect(Collectors.toList());
    
    // 将List<String>对象转换为List<User>对象
    List<User> userList = listStr.stream().map(name-> {
        User user= new User();
        user.setName(name);
        user.setPassword(null);
        user.setAge(null);
        return user;
    }).collect(Collectors.toList());
    // 简写
    List<User> userList = listStr.stream().map(name-> new User(name)).collect(Collectors.toList());
    
    // 将List<User>对象转换为List<UserInfo>对象
    List<UserInfo> collect = userList.stream().map(l -> new UserInfo(l.getName(), l.getPassword())).collect(Collectors.toList());
    

    Stream流的sort使用

    List<String> list = Arrays.asList("张三", "李四", "王五", "小六");
    list.stream().limit(3).sorted().forEach(System.out::println);
    
    // 先排序后比较效率更高
    List<User> listUser = new ArrayList<User>();
    listUser.stream().limit(3).sorted((u1, u2) -> u1.getName().compareTo(u2.getName())).collect(Collectors.toList());
    

    Stream流的max/min/distinct使用

    // 示例一:取最大/最小值
    List<String> list13 = Arrays.asList("zhangsan","lisi","wangwu","xuwujing");
    int maxLines = list13.stream().mapToInt(String::length).max().getAsInt();
    int minLines = list13.stream().mapToInt(String::length).min().getAsInt();
    System.out.println("最长字符的长度:" + maxLines+",最短字符的长度:"+minLines);
    
    // 示例二:得到去重之后的数据
    String lines = "good good study day day up";
    List<String> list14 = new ArrayList<String>();
    list14.add(lines);
    List<String> words = list14.stream().flatMap(line -> Stream.of(line.split(" "))).filter(word -> word.length() > 0).map(String::toLowerCase).distinct().sorted().collect(Collectors.toList());
    System.out.println("去重复之后:" + words);
    

    Stream流的reduce使用

    reduce 主要作用是把 Stream 元素组合起来进行操作。

    // 示例一:字符串连接
    String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat);
    System.out.println("字符串拼接:" + concat);
    
    // 示例二:得到最小值
    double minValue = Stream.of(-4.0, 1.0, 3.0, -2.0).reduce(Double.MAX_VALUE, Double::min);
    System.out.println("最小值:" + minValue);
    
    // 示例三:求和
    // 求和, 无起始值
    int sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
    System.out.println("有无起始值求和:" + sumValue);
    
    // 求和, 有起始值
    sumValue = Stream.of(1, 2, 3, 4).reduce(1, Integer::sum);
    System.out.println("有起始值求和:" + sumValue);
    
    // 示例四:过滤拼接
    concat = Stream.of("a", "B", "c", "D", "e", "F").filter(x -> x.compareTo("Z") > 0).reduce("", String::concat);
    System.out.println("过滤和字符串连接:" + concat);
    

    Stream流的Match使用

    • allMatch:Stream 中全部元素符合则返回 true ;
    • anyMatch:Stream 中只要有一个元素符合则返回 true;
    • noneMatch:Stream 中没有一个元素符合则返回 true。
    // 检查数据是否符合
    boolean all = lists.stream().allMatch(u -> u.getId() > 3);
    System.out.println("是否都大于3:" + all);
    
    boolean any = lists.stream().anyMatch(u -> u.getId() > 3);
    System.out.println("是否有一个大于3:" + any);
    
    boolean none = lists.stream().noneMatch(u -> u.getId() > 3);
    System.out.println("是否没有一个大于3的:" + none);
    

    双冒号之方法引用

    Integer::parseInt;    // 方法引用
    Integer::new;         // 引入构造方法
    
    interface Demo{
        int method(String s);
    }
    public class TestTwo {
    
        public static void main(String[] args) {
    
            // 匿名内部类调用
            Demo demo1 = new Demo() {
                @Override
                public int method(String s) {
                    return Integer.parseInt(s);
                }
            };
            int v1 = demo1.method("111");
            System.out.println(v1);
    
            // Lambda表达式
            Demo demo2 = s -> {
                return Integer.parseInt(s);
            };
            int v2 = demo2.method("222");
            System.out.println(v2);
    
            // Lambda表达式 单行简写
            Demo demo3 = s -> Integer.parseInt(s);
            int v3 = demo3.method("333");
            System.out.println(v3);
    
            // 方法引用 双冒号::
            Demo demo4 = Integer::parseInt;
            int v4 = demo4.method("444");
            System.out.println(v4);
    
            // 引入构造方法
            Demo demo5 = Integer::new;
            int v5 = demo5.method("555");
            System.out.println(v5);
    
             // 排序示例
            List<Integer> list = Arrays.asList(20, 53, 16, 95, 100);
            // 方式一:匿名内部类
            list.sort(new Comparator<Integer>() {
                @Override
                public int compare(Integer o1, Integer o2) {
                    return Integer.compare(o1,o2);
                }
            });
            // 方式二:Lambda表达式
            list.sort((x,y) -> Integer.compare(x,y));
    
            // 方式三:静态方法引用
            list.sort(Integer::compare);
    
            // 打印
            list.forEach(System.out::println);
        }
    }
    
  • 相关阅读:
    java RSA加密解密
    spring boot 错误处理机制
    Redis 服务常见的几个错误解决方案
    Nginx目录遍历功能时间相差8小时
    翻过大山越过海洋看到了什么
    【分享】分层明确高度定制化的 Python Flask MVC
    编程浪子客服系统开源啦
    快速搭建一个直播Demo
    免费为网站加上HTTPS
    Mac 下安装Fiddler抓包工具
  • 原文地址:https://www.cnblogs.com/zhaojinhui/p/16697039.html
Copyright © 2020-2023  润新知