IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> Lambda表达式 -> 正文阅读

[Java知识库]Lambda表达式

Lambda表达式

1. 前序

1.1 需求1

  • 假如说有这样一个需求,需要将一个list集合按照某种顺序排序。

  • 一般的做法

  • public class TestMain {
        @Test
        public void test01(){
            List<String> list = Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
            Collections.sort(list, new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    return -Integer.compare(Integer.parseInt(o1),Integer.parseInt(o2));
                }
            });
            System.out.println(list.toString());
        }
    }
    
  • 使用lambda表达式

  • public class TestMain {
        @Test
        public void test01(){
        
            List<String> list = Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8", "9", "0");
            
            // 传统实现
            Collections.sort(list, new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                    return -Integer.compare(Integer.parseInt(o1),Integer.parseInt(o2));
                }
            });
            System.out.println(list.toString());
            
            // lambda表达式实现
            Comparator<String> comparator = (x,y) -> -Integer.compare(Integer.parseInt(x),Integer.parseInt(y));
            Collections.sort(list,comparator);
            System.out.println(list.toString());
        }
    }
    

1.2 需求2

  • 假设有一个员工类

  • /**
     * @author 16541
     */
    public class Employee {
        /**
         * 员工姓名
         */
        public String name;
        /**
         * 员工年龄
         */
        public Integer age;
        /**
         * 员工薪资
         */
        public Double salary;
    
        public Employee() {
        }
    
        public Employee(String name, Integer age, Double salary) {
            this.name = name;
            this.age = age;
            this.salary = salary;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public Double getSalary() {
            return salary;
        }
    
        public void setSalary(Double salary) {
            this.salary = salary;
        }
    
        @Override
        public String toString() {
            return "Employee{" +
                    "name='" + name + '\'' +
                    ", age=" + age +
                    ", salary=" + salary +
                    '}';
        }
    }
    
    

1.2.1 选出员工年龄大于25岁的

  • @Test
    public void test02(){
        	// 员工集合
            List<Employee> employees = Arrays.asList(
                    new Employee("张三", 30, 9999.99),
                    new Employee("李四", 20, 7777.77),
                    new Employee("王五", 10, 6666.66),
                    new Employee("陈六", 27, 4444.44),
                    new Employee("田七", 35, 3333.33)
            );
        
            List<Employee> list01 = filterEmployeeByAge(employees);
            for (Employee employee:list01){
                System.out.println(employee);
            }
    }
    
    public List<Employee> filterEmployeeByAge(List<Employee> employees){
            List<Employee> list = new ArrayList<>();
            for (Employee employee:employees){
                if (employee.getAge() > 25){
                    list.add(employee);
                }
            }
            return list;
    }
    运行结果:
    Employee{name='张三', age=30, salary=9999.99}
    Employee{name='陈六', age=27, salary=4444.44}
    Employee{name='田七', age=35, salary=3333.33}
    

1.2.2 选出 薪资大于 5000 的

  • @Test
        public void test02(){
            // 员工集合
            List<Employee> employees = Arrays.asList(
                    new Employee("张三", 30, 9999.99),
                    new Employee("李四", 20, 7777.77),
                    new Employee("王五", 10, 6666.66),
                    new Employee("陈六", 27, 4444.44),
                    new Employee("田七", 35, 3333.33)
            );
            
            List<Employee> list02 = filterEmployeeBySalary(employees);
            for (Employee employee:list02){
                System.out.println(employee);
            }
        }
        
    public List<Employee> filterEmployeeBySalary(List<Employee> employees){
            List<Employee> list = new ArrayList<>();
            for (Employee employee:employees){
                if (employee.getSalary() > 5000){
                    list.add(employee);
                }
            }
            return list;
        }
    

1.2.3 策略设计模式

  • 发现这两个方法其实大致相同,只是一个是年龄,一个是薪资,可以进行改进

  • /**
     * @author 16541
     */
    public interface MyPredicate<T> {
        /**
         * 用于判断条件是否成立
         * @param t
         * @return
         */
        boolean test(T t);
    }
    
  • /**
     * @author 16541
     */
    public class FilterEmployeeByAge implements MyPredicate<Employee> {
        @Override
        public boolean test(Employee employee) {
            return employee.getAge() > 25;
        }
    }
    
  • /**
     * @author 16541
     */
    public class FilterEmployeeBySalary implements MyPredicate<Employee> {
        @Override
        public boolean test(Employee employee) {
            return employee.getSalary() > 5000;
        }
    }
    
  • @Test
        public void test03(){
            // 员工集合
            List<Employee> employees = Arrays.asList(
                    new Employee("张三", 30, 9999.99),
                    new Employee("李四", 20, 7777.77),
                    new Employee("王五", 10, 6666.66),
                    new Employee("陈六", 27, 4444.44),
                    new Employee("田七", 35, 3333.33)
            );
            List<Employee> list = filterEmployee(employees, new FilterEmployeeByAge());
            for (Employee employee : list){
                System.out.println(employee);
            }
            System.out.println("=======================================");
            List<Employee> list1 = filterEmployee(employees, new FilterEmployeeBySalary());
            for (Employee employee : list1){
                System.out.println(employee);
            }
        }
        public List<Employee> filterEmployee(List<Employee> employees, MyPredicate<Employee> myPredicate){
            List<Employee> list = new ArrayList<>();
            for (Employee employee : employees){
                if (myPredicate.test(employee)){
                    list.add(employee);
                }
            }
            return list;
        }
    
  • 策略设计模式,定义一个统一的接口,根据不同的需求,有不同的实现,当需求变动时,只需要修改添加的实现类就可以了,

1.2.4 lambda表达式

  • 上述的代码需要定义各种不同的实现类,其实看起来也是挺麻烦的,接下来用lambda实现

  • /**
     * @author 16541
     */
    public interface MyPredicate<T> {
        /**
         * 用于判断条件是否成立
         * @param t
         * @return
         */
        boolean test(T t);
    }
    
  • @Test
        public void test04(){
            // 员工集合
            List<Employee> employees = Arrays.asList(
                    new Employee("张三", 30, 9999.99),
                    new Employee("李四", 20, 7777.77),
                    new Employee("王五", 10, 6666.66),
                    new Employee("陈六", 27, 4444.44),
                    new Employee("田七", 35, 3333.33)
            );
            List<Employee> list = filterEmployee(employees, e -> e.getAge() > 25);
            for (Employee employee : list){
                System.out.println(employee);
            }
            System.out.println("=======================================");
            List<Employee> list1 = filterEmployee(employees, e -> e.getSalary() > 5000);
            for (Employee employee : list1){
                System.out.println(employee);
            }
        }
        
        
    public List<Employee> filterEmployee(List<Employee> employees, MyPredicate<Employee> myPredicate){
            List<Employee> list = new ArrayList<>();
            for (Employee employee : employees){
                if (myPredicate.test(employee)){
                    list.add(employee);
                }
            }
            return list;
        }
    
  • 这里依然使用了 filterEmployee方法,不过传入的方式改用了 lambda 方式

  • 也就是说 e -> e.getAge() > 25就相当于 filterEmployeeByAge类,e -> e.getSalary() > 5000就相当于 filterEmployeeBySalary

1.2.5 Stream+lambda

  • 上面的代码还可以结合Stream流进行改进

  • @Test
        public void test05(){
            // 员工集合
            List<Employee> employees = Arrays.asList(
                    new Employee("张三", 30, 9999.99),
                    new Employee("李四", 20, 7777.77),
                    new Employee("王五", 10, 6666.66),
                    new Employee("陈六", 27, 4444.44),
                    new Employee("田七", 35, 3333.33)
            );
            employees.stream()
                    .filter(e -> e.getAge() > 25)
                    .forEach(System.out::println);
        }
    
  • 是不是感觉有点不像java代码了,噗哈哈哈!好了,现在开始进入正题

2. lambda表达式

2.1 基础语法

  • java8中引入了一个新的操作符 “->” , 箭头操作符或者lambda操作符

  • 箭头操作符将lambda表达式分成了两部分

    • 左侧:lambda表达式的参数列表,可以理解为实现接口的方法参数
    • 右侧:所需要执行的功能,即 lambda 体,可以简单理解为对应的接口实现。
  • 语法一: 无参数,无返回值

    • () -> System.out.println();
  • 语法二: 一个参数,无返回值

    • (x) -> System.out.plrintln(x)
    • 左侧的括号可省略x -> System.out.plrintln(x)
  • 语法三: 两个参数,有返回值

    • Comparator<Integer> comparator = (x,y) -> {    
          System.out.println(x+" "+y);    
          return Integer.compare(x,y);
      };
      
    • 若lambda体中只有一条语句,可以简写为 Comparator<Integer> comparator = (x,y) -> Integer.compare(x,y);,省略大括号和 return;

  • 左侧的参数的数据类型可以不用写,JVM会根据上下发自动判断。

2.2 内置函数式接口

  • 需要注意的是,lambda实现的接口,你会发现这些接口中只有一个方法,如果接口中有多个方法,lambda表达式无法判断要实现哪个方法,所以,lambda表达式的使用场景只适用于函数式接口中。接口中只有一个方法的接口叫函数式接口。

  • 另外,有人会问了,难道每次使用lambda表达式时,都需要自己先定义一个函数式接口么?

  • 答案是不用的,java中内置了四个核心的函数式接口,

  • @FunctionalInterface
    public interface Consumer<T> {
    
        /**
         * Performs this operation on the given argument.
         *
         * @param t the input argument
         */
        void accept(T t);
    
        /**
         * Returns a composed {@code Consumer} that performs, in sequence, this
         * operation followed by the {@code after} operation. If performing either
         * operation throws an exception, it is relayed to the caller of the
         * composed operation.  If performing this operation throws an exception,
         * the {@code after} operation will not be performed.
         *
         * @param after the operation to perform after this operation
         * @return a composed {@code Consumer} that performs in sequence this
         * operation followed by the {@code after} operation
         * @throws NullPointerException if {@code after} is null
         */
        default Consumer<T> andThen(Consumer<? super T> after) {
            Objects.requireNonNull(after);
            return (T t) -> { accept(t); after.accept(t); };
        }
    }
    
  • @FunctionalInterface
    public interface Supplier<T> {
    
        /**
         * Gets a result.
         *
         * @return a result
         */
        T get();
    }
    
  • @FunctionalInterface
    public interface Function<T, R> {
    
        /**
         * Applies this function to the given argument.
         *
         * @param t the function argument
         * @return the function result
         */
        R apply(T t);
    
        /**
         * Returns a composed function that first applies the {@code before}
         * function to its input, and then applies this function to the result.
         * If evaluation of either function throws an exception, it is relayed to
         * the caller of the composed function.
         *
         * @param <V> the type of input to the {@code before} function, and to the
         *           composed function
         * @param before the function to apply before this function is applied
         * @return a composed function that first applies the {@code before}
         * function and then applies this function
         * @throws NullPointerException if before is null
         *
         * @see #andThen(Function)
         */
        default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
            Objects.requireNonNull(before);
            return (V v) -> apply(before.apply(v));
        }
    
        /**
         * Returns a composed function that first applies this function to
         * its input, and then applies the {@code after} function to the result.
         * If evaluation of either function throws an exception, it is relayed to
         * the caller of the composed function.
         *
         * @param <V> the type of output of the {@code after} function, and of the
         *           composed function
         * @param after the function to apply after this function is applied
         * @return a composed function that first applies this function and then
         * applies the {@code after} function
         * @throws NullPointerException if after is null
         *
         * @see #compose(Function)
         */
        default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
            Objects.requireNonNull(after);
            return (T t) -> after.apply(apply(t));
        }
    
        /**
         * Returns a function that always returns its input argument.
         *
         * @param <T> the type of the input and output objects to the function
         * @return a function that always returns its input argument
         */
        static <T> Function<T, T> identity() {
            return t -> t;
        }
    }
    
  • @FunctionalInterface
    public interface Predicate<T> {
    
        /**
         * Evaluates this predicate on the given argument.
         *
         * @param t the input argument
         * @return {@code true} if the input argument matches the predicate,
         * otherwise {@code false}
         */
        boolean test(T t);
    
        /**
         * Returns a composed predicate that represents a short-circuiting logical
         * AND of this predicate and another.  When evaluating the composed
         * predicate, if this predicate is {@code false}, then the {@code other}
         * predicate is not evaluated.
         *
         * <p>Any exceptions thrown during evaluation of either predicate are relayed
         * to the caller; if evaluation of this predicate throws an exception, the
         * {@code other} predicate will not be evaluated.
         *
         * @param other a predicate that will be logically-ANDed with this
         *              predicate
         * @return a composed predicate that represents the short-circuiting logical
         * AND of this predicate and the {@code other} predicate
         * @throws NullPointerException if other is null
         */
        default Predicate<T> and(Predicate<? super T> other) {
            Objects.requireNonNull(other);
            return (t) -> test(t) && other.test(t);
        }
    
        /**
         * Returns a predicate that represents the logical negation of this
         * predicate.
         *
         * @return a predicate that represents the logical negation of this
         * predicate
         */
        default Predicate<T> negate() {
            return (t) -> !test(t);
        }
    
        /**
         * Returns a composed predicate that represents a short-circuiting logical
         * OR of this predicate and another.  When evaluating the composed
         * predicate, if this predicate is {@code true}, then the {@code other}
         * predicate is not evaluated.
         *
         * <p>Any exceptions thrown during evaluation of either predicate are relayed
         * to the caller; if evaluation of this predicate throws an exception, the
         * {@code other} predicate will not be evaluated.
         *
         * @param other a predicate that will be logically-ORed with this
         *              predicate
         * @return a composed predicate that represents the short-circuiting logical
         * OR of this predicate and the {@code other} predicate
         * @throws NullPointerException if other is null
         */
        default Predicate<T> or(Predicate<? super T> other) {
            Objects.requireNonNull(other);
            return (t) -> test(t) || other.test(t);
        }
    
        /**
         * Returns a predicate that tests if two arguments are equal according
         * to {@link Objects#equals(Object, Object)}.
         *
         * @param <T> the type of arguments to the predicate
         * @param targetRef the object reference with which to compare for equality,
         *               which may be {@code null}
         * @return a predicate that tests if two arguments are equal according
         * to {@link Objects#equals(Object, Object)}
         */
        static <T> Predicate<T> isEqual(Object targetRef) {
            return (null == targetRef)
                    ? Objects::isNull
                    : object -> targetRef.equals(object);
        }
    }
    
    
  • 使用的时候,可以直接把这几个接口当参数传入,用lambda表达式实现其方法就可以了。

睡觉了,有空再补完剩下的。

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-08-23 16:31:00  更:2021-08-23 16:34:12 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 10:04:45-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码