zoukankan      html  css  js  c++  java
  • Lambda表达式常用代码示例

    Lambda表达式常用代码示例

    2017-10-24

    目录

    1 Lambda表达式是什么
    2 Lambda表达式语法
    3 函数式接口是什么
      3.1 常用函数式接口
    4 Lambdas和Streams结合使用
      4.1 使用forEach方法
      4.2 使用过滤器filter方法
      4.3 使用limit方法
      4.4 使用sorted方法
      4.5 使用map方法
      4.6 使用parallelStream方法
      4.7 使用summaryStatistics方法
    参考 

    1 Lambda表达式是什么 


     返回

    Lambda 表达式是一种匿名函数(对 Java 而言这并不完全正确。在Java中,Lambda 表达式是对象,他们必须依附于一类特别的对象类型——函数式接口(functional interface))。Lambda表达式是Java SE 8中一个重要的新特性。lambda表达式就和方法一样,它提供了一个正常的参数列表(argument)和一个使用这些参数的主体(body)。

    Lambda 表达式为 Java 添加了缺失的函数式编程特点,使我们能将函数当做一等公民看待。

    Lambda表达式还增强了集合库。 Java SE 8添加了2个对集合数据进行批量操作的包: java.util.function 包以及java.util.stream 包。 流(stream)就如同迭代器(iterator),但附加了许多额外的功能。 总的来说,lambda表达式和 stream 是自Java语言添加泛型(Generics)和注解(annotation)以来最大的变化。

    2 Lambda表达式语法


     返回

    Java 中的 Lambda 表达式通常使用 (argument) -> {body} 语法书写,例如:

    (arg1, arg2...) -> { body }
    (type1 arg1, type2 arg2...) -> { body }

    以下是一些 Lambda 表达式的例子:

    (int a, int b) -> {  return a + b; }
    () -> System.out.println("Hello World");
    (String s) -> { System.out.println(s); }
    () -> 42
    () -> { return 3.1415 };

    Lambda表达式结构说明:

    • 一个 Lambda 表达式可以有零个或多个参数
    • 参数的类型既可以明确声明,也可以根据上下文来推断。例如:(int a)与(a)效果相同
    • 所有参数需包含在圆括号内,参数之间用逗号相隔。例如:(a, b) 或 (int a, int b) 或 (String a, int b, float c)
    • 空圆括号代表参数集为空。例如:() -> 42
    • 当只有一个参数,且其类型可推导时,圆括号()可省略。例如:a -> return a*a
    • Lambda 表达式的主体可包含零条或多条语句
    • 如果 Lambda 表达式的主体只有一条语句,花括号{}可省略。匿名函数的返回类型与该主体表达式一致
    • 如果 Lambda 表达式的主体包含一条以上语句,则表达式必须包含在花括号{}中(形成代码块)。匿名函数的返回类型与代码块的返回类型一致,若没有返回则为空

    3 函数式接口是什么


     返回

    函数式接口是只包含一个抽象方法声明的接口。

    java.lang.Runnable 就是一种函数式接口,在 Runnable 接口中只声明了一个方法 void run(),相似地,ActionListener 接口也是一种函数式接口,我们使用匿名内部类来实例化函数式接口的对象,有了 Lambda 表达式,这一方式可以得到简化。Runnable接口代码如下:

    @FunctionalInterface
    public interface Runnable {
        public abstract void run();
    }

     每个 Lambda 表达式都能隐式地赋值给函数式接口。如下代码:

    Runnable r = () -> System.out.println("hello world");

    Runnable的Lambda表达式和匿名内部类的使用示例

    public void sample01() {
            // 1.1使用匿名内部类
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("1.1 Hello world !");
                }
            }).start();
    
            // 1.2使用 lambda expression
            new Thread(() -> System.out.println("1.2 Hello world !")).start();
    
            // 2.1使用匿名内部类
            Runnable race1 = new Runnable() {
                @Override
                public void run() {
                    System.out.println("1.3 Hello world !");
                }
            };
    
            // 2.2使用 lambda expression
            Runnable race2 = () -> System.out.println("1.4 Hello world !");
    
            // 直接调用 run 方法(没开新线程哦!)
            race1.run();
            race2.run();
        }
    View Code

    自定义函数式接口及Lambda表达式和匿名内部类的使用示例

    WorkerInterface.java

    //定义一个函数式接口
    @FunctionalInterface
    public interface WorkerInterface {
        public void doSomeWork();
    }
    View Code

    WorkerInterfaceTest.java

    public class WorkerInterfaceTest {
        public static void main(String [] args) {
            //invoke doSomeWork using Annonymous class
            execute(new WorkerInterface() {
                @Override
                public void doSomeWork() {
                    System.out.println("Worker invoked using Anonymous class");
                }
            });
    
            //invoke doSomeWork using Lambda expression
            execute( () -> System.out.println("Worker invoked using Lambda expression") );
        }
    
        public static void execute(WorkerInterface worker) {
            worker.doSomeWork();
        }
    }
    View Code

    3.1 常用函数式接口

    Predicate、Function、Consumer、Supplier示例代码:

            //Predicate 接口只有一个参数,返回boolean类型。。
            Predicate<String> predicate = (s) -> s.length() > 3;
            System.out.println(predicate.test("foo"));   // false
            Predicate<Boolean> nonNull = Objects::nonNull;
            System.out.println(nonNull.test(false));     // true
    
            //Function 接口接受一个参数,返回一个结果,并附带了一些可以和其他函数组合的默认方法(compose, andThen)
            Function<String, Integer> toInteger = Integer::valueOf;
            System.out.println(toInteger.apply("123").getClass());    //class java.lang.Integer
            Function<String, String> backToString = toInteger.andThen(String::valueOf);
            System.out.println(backToString.apply("123").getClass()); //class java.lang.String
    
            //Consumer 接口接受一个参数,没有返回结果。
            Consumer<Cat> greeter = (c) -> System.out.println("Hello, " + c.name);
            Cat cat=new Cat("Tom", 3);
            greeter.accept(cat);    //Hello, Tom
    
            //Supplier接口没有参数,。
            Supplier<Double> number = () -> Math.random();
            System.out.println(number.get());  //0.8765252430762529
    View Code

    使用Lambdas排序集合

    在Java中,Comparator 类被用来排序集合。

    使用匿名内部类或Lambda表达式根据 name 排序 players:

            String[] players = {"Rafael Nadal", "Novak Djokovic", "Stanislas Wawrinka", "David Ferrer",
                                "Roger Federer", "Andy Murray", "Tomas Berdych", "Juan Martin Del Potro",
                                "Richard Gasquet", "John Isner"};
    
            // 1.1 使用匿名内部类根据 name 排序 players
            Arrays.sort(players, new Comparator<String>() {
                @Override
                public int compare(String s1, String s2) {
                    return (s1.compareTo(s2));
                }
            });
    
            // 1.2 使用 lambda expression 排序 players
            Comparator<String> sortByName = (String s1, String s2) -> (s1.compareTo(s2));
            Arrays.sort(players, sortByName);
    
            // 1.3 也可以采用如下形式:
            Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2)));
    View Code

     其他排序:

            // 2.1 使用匿名内部类根据 surname 排序 players
            Arrays.sort(players, new Comparator<String>() {
                @Override
                public int compare(String s1, String s2) {
                    return (s1.substring(s1.indexOf(" ")).compareTo(s2.substring(s2.indexOf(" "))));
                }
            });
    
            // 2.2 使用 lambda expression 排序,根据 surname
            Comparator<String> sortBySurname = (String s1, String s2) ->
                    ( s1.substring(s1.indexOf(" ")).compareTo( s2.substring(s2.indexOf(" ")) ) );
            Arrays.sort(players, sortBySurname);
    
            // 2.3 或者这样,怀疑原作者是不是想错了,括号好多...
            Arrays.sort(players, (String s1, String s2) ->
                    ( s1.substring(s1.indexOf(" ")).compareTo( s2.substring(s2.indexOf(" ")) ) )
            );
    
            // 3.1 使用匿名内部类根据 name lenght 排序 players
            Arrays.sort(players, new Comparator<String>() {
                @Override
                public int compare(String s1, String s2) {
                    return (s1.length() - s2.length());
                }
            });
    
            // 3.2 使用 lambda expression 排序,根据 name lenght
            Comparator<String> sortByNameLenght = (String s1, String s2) -> (s1.length() - s2.length());
            Arrays.sort(players, sortByNameLenght);
    
            // 3.3 or this
            Arrays.sort(players, (String s1, String s2) -> (s1.length() - s2.length()));
    
            // 4.1 使用匿名内部类排序 players, 根据最后一个字母
            Arrays.sort(players, new Comparator<String>() {
                @Override
                public int compare(String s1, String s2) {
                    return (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1));
                }
            });
    
            // 4.2 使用 lambda expression 排序,根据最后一个字母
            Comparator<String> sortByLastLetter =
                    (String s1, String s2) ->
                            (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1));
            Arrays.sort(players, sortByLastLetter);
    
            // 4.3 or this
            Arrays.sort(players, (String s1, String s2) -> (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1)));
    View Code

    4 Lambdas和Streams结合使用


     返回

    Stream是对集合的包装,通常和lambda一起使用。 使用lambdas可以支持许多操作,如 map, filter, limit, sorted, count, min, max, sum, collect 等等。 同样,Stream使用懒运算,他们并不会真正地读取所有数据,遇到像getFirst() 这样的方法就会结束链式语法。

    Person.java代码:

    public class Person {
        private String firstName;
        private String lastName;
        private String job;
        private String gender;
        private int salary;
        private int age;
    
        public Person(String firstName, String lastName, String job,
                      String gender, int age, int salary) {
            this.setFirstName(firstName);
            this.setLastName(lastName);
            this.setGender(gender);
            this.setAge(age);
            this.setJob(job);
            this.setSalary(salary);
        }
    
        public String getFirstName() {
            return firstName;
        }
    
        public void setFirstName(String firstName) {
            this.firstName = firstName;
        }
    
        public String getLastName() {
            return lastName;
        }
    
        public void setLastName(String lastName) {
            this.lastName = lastName;
        }
    
        public String getJob() {
            return job;
        }
    
        public void setJob(String job) {
            this.job = job;
        }
    
        public String getGender() {
            return gender;
        }
    
        public void setGender(String gender) {
            this.gender = gender;
        }
    
        public int getSalary() {
            return salary;
        }
    
        public void setSalary(int salary) {
            this.salary = salary;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    }
    View Code

    初始化Person代码:

           List<Person> javaProgrammers = new ArrayList<Person>() {
                {
                    add(new Person("Elsdon", "Jaycob", "Java programmer", "male", 43, 2000));
                    add(new Person("Tamsen", "Brittany", "Java programmer", "female", 23, 1500));
                    add(new Person("Floyd", "Donny", "Java programmer", "male", 33, 1800));
                    add(new Person("Sindy", "Jonie", "Java programmer", "female", 32, 1600));
                    add(new Person("Vere", "Hervey", "Java programmer", "male", 22, 1200));
                    add(new Person("Maude", "Jaimie", "Java programmer", "female", 27, 1900));
                    add(new Person("Shawn", "Randall", "Java programmer", "male", 30, 2300));
                    add(new Person("Jayden", "Corrina", "Java programmer", "female", 35, 1700));
                    add(new Person("Palmer", "Dene", "Java programmer", "male", 33, 2000));
                    add(new Person("Addison", "Pam", "Java programmer", "female", 34, 1300));
                }
            };
    
            List<Person> phpProgrammers = new ArrayList<Person>() {
                {
                    add(new Person("Jarrod", "Pace", "PHP programmer", "male", 34, 1550));
                    add(new Person("Clarette", "Cicely", "PHP programmer", "female", 23, 1200));
                    add(new Person("Victor", "Channing", "PHP programmer", "male", 32, 1600));
                    add(new Person("Tori", "Sheryl", "PHP programmer", "female", 21, 1000));
                    add(new Person("Osborne", "Shad", "PHP programmer", "male", 32, 1100));
                    add(new Person("Rosalind", "Layla", "PHP programmer", "female", 25, 1300));
                    add(new Person("Fraser", "Hewie", "PHP programmer", "male", 36, 1100));
                    add(new Person("Quinn", "Tamara", "PHP programmer", "female", 21, 1000));
                    add(new Person("Alvin", "Lance", "PHP programmer", "male", 38, 1600));
                    add(new Person("Evonne", "Shari", "PHP programmer", "female", 40, 1800));
                }
            };
    View Code

    4.1 使用forEach方法

    使用forEach方法显示所有程序员姓名:

            System.out.println("所有程序员的姓名:");
            javaProgrammers.forEach((p) -> System.out.println(String.format("%s %s; ", p.getFirstName(), p.getLastName())));
            phpProgrammers.forEach((p) -> System.out.println(String.format("%s %s; ", p.getFirstName(), p.getLastName())));
    View Code

    ForEach代码:

        public interface Iterable<T> {
            default void forEach(Consumer<? super T> action) {
                Objects.requireNonNull(action);
                for (T t : this) {
                    action.accept(t);
                }
            }
        ...
        }
    View Code

    使用forEach方法,增加程序员的工资5%:

            System.out.println("给程序员加薪 5% :");
            Consumer<Person> giveRaise = e -> e.setSalary(e.getSalary() / 100 * 5 + e.getSalary());
            javaProgrammers.forEach(giveRaise);
            phpProgrammers.forEach(giveRaise);
    View Code

    4.2 使用过滤器filter方法 

            System.out.println("下面是月薪超过 $1,400 的PHP程序员:");
            phpProgrammers.stream()
                    .filter((p) -> (p.getSalary() > 1400))
                    .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));
    
            // 定义 filters  
            Predicate<Person> ageFilter = (p) -> (p.getAge() > 25);
            Predicate<Person> salaryFilter = (p) -> (p.getSalary() > 1400);
            Predicate<Person> genderFilter = (p) -> ("female".equals(p.getGender()));
    
            System.out.println("下面是年龄大于 25岁且月薪在$1,400以上的女PHP程序员:");
            phpProgrammers.stream()
                    .filter(ageFilter)
                    .filter(salaryFilter)
                    .filter(genderFilter)
                    .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));
    View Code

    4.3 使用limit方法

     使用limit方法可以限制结果集的个数:

            System.out.println("最前面的3个 Java programmers:");
            javaProgrammers.stream()
                    .limit(3)
                    .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));
    
    
            System.out.println("最前面的3个女性 Java programmers:");
            javaProgrammers.stream()
                    .filter(genderFilter)
                    .limit(3)
                    .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));
    View Code

    4.4 使用sorted方法

    使用sorted方法进行排序:

            System.out.println("根据 name 排序,并显示前5个 Java programmers:");
            List<Person> sortedJavaProgrammers = javaProgrammers
                    .stream()
                    .sorted((p, p2) -> (p.getFirstName().compareTo(p2.getFirstName())))
                    .limit(5)
                    .collect(toList());
    
            sortedJavaProgrammers.forEach((p) -> System.out.printf("%s %s; %n", p.getFirstName(), p.getLastName()));
    
            System.out.println("根据 salary 排序 Java programmers:");
            sortedJavaProgrammers = javaProgrammers
                    .stream()
                    .sorted( (p, p2) -> (p.getSalary() - p2.getSalary()) )
                    .collect( toList() );
            sortedJavaProgrammers.forEach((p) -> System.out.printf("%s %s; %n", p.getFirstName(), p.getLastName()));
    View Code

    使用min和max方法:

            System.out.println("工资最低的 Java programmer:");
            Person pers = javaProgrammers
                    .stream()
                    .min((p1, p2) -> (p1.getSalary() - p2.getSalary()))
                    .get();
    
            System.out.printf("Name: %s %s; Salary: $%,d.", pers.getFirstName(), pers.getLastName(), pers.getSalary());
    
            System.out.println("工资最高的 Java programmer:");
            Person person = javaProgrammers
                    .stream()
                    .max((p, p2) -> (p.getSalary() - p2.getSalary()))
                    .get();
    
            System.out.printf("Name: %s %s; Salary: $%,d.", person.getFirstName(), person.getLastName(), person.getSalary());
    View Code

    4.5 使用map方法

    结合 map 方法,我们可以使用 collect 方法来将我们的结果集放到一个字符串,一个 Set 或一个TreeSet中:

            System.out.println("将 PHP programmers 的 first name 拼接成字符串:");
            String phpDevelopers = phpProgrammers
                    .stream()
                    .map(Person::getFirstName)
                    .collect(joining(" ; ")); // 在进一步的操作中可以作为标记(token)
            System.out.println(phpDevelopers);  //Jarrod ; Clarette ; Victor ; Tori ; Osborne ; Rosalind ; Fraser ; Quinn ; Alvin ; Evonne
    
            System.out.println("将 Java programmers 的 first name 存放到 Set:");
            Set<String> javaDevFirstName = javaProgrammers
                    .stream()
                    .map(Person::getFirstName)
                    .collect(toSet());
            System.out.println(javaDevFirstName);  //[Elsdon, Shawn, Palmer, Addison, Maude, Floyd, Vere, Tamsen, Jayden, Sindy]
    
            System.out.println("将 Java programmers 的 last name 存放到 TreeSet:");
            TreeSet<String> javaDevLastName = javaProgrammers
                    .stream()
                    .map(Person::getLastName)
                    .collect(toCollection(TreeSet::new));
            System.out.println(javaDevLastName);  //[Brittany, Corrina, Dene, Donny, Hervey, Jaimie, Jaycob, Jonie, Pam, Randall]
    View Code

    4.6 使用parallelStream方法

    当需要为多核系统优化时,可以 parallelStream().forEach(),只是此时原有元素的次序没法保证,并行的情况下将改变串行时操作的行为:

            System.out.println("计算付给 Java programmers 的所有money:");
            int totalSalary = javaProgrammers
                    .parallelStream()
                    .mapToInt(p -> p.getSalary())
                    .sum();
    View Code

    4.7 使用summaryStatistics方法

    使用summaryStatistics方法获得stream 中元素的各种汇总数据:

           //计算 count, min, max, sum, and average for numbers
            List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
            IntSummaryStatistics stats = numbers
                    .stream()
                    .mapToInt((x) -> x)
                    .summaryStatistics();
    
            System.out.println("List中最大的数字 : " + stats.getMax());
            System.out.println("List中最小的数字 : " + stats.getMin());
            System.out.println("所有数字的总和   : " + stats.getSum());
            System.out.println("所有数字的平均值 : " + stats.getAverage());
    View Code

    参考

    [1] 深入浅出 Java 8 Lambda 表达式

    [2] Java中Lambda表达式的使用

    [3] Java 8 中的 Streams API 详解

    [4] Lambda 表达式讲解

  • 相关阅读:
    org.apache.maven.archiver.MavenArchiver.getManifest
    网易云信发送短信验证码
    background-attachment:fixed;
    background-size属性100% cover contain
    width:100% width:auto 区别
    背景图全屏显示
    多行文字的垂直居中
    路径问题../绝对路径/
    用position子绝父相和css3动画,当鼠标一上去元素从底部慢慢向上
    前置后置运算符重载
  • 原文地址:https://www.cnblogs.com/Ming8006/p/7718275.html
Copyright © 2011-2022 走看看