• Android学习笔记--JDK1.8的新特性


    1.接口默认方法

    JDK8允许我们给接口添加一个非抽象的方法实现,只需要使用default关键字即可。

    interface Formula{

    double calculate(int a);

    default double sqrt(int a){

        return Math.sqrt(a);

    }

    }

    实现了Formula接口的子类可以直接使用sqrt方法。

    formula被实现为一个匿名类的实例

    Formula formula = new Formula() {

        @Override

        public double calculate(int a) {

            return sqrt(a * 100);

        }

    };

    formula.calculate(100);     // 100.0

    formula.sqrt(16);           // 4.0

    1.Lambda表达式

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

    1Lambda表达式的语法

     基本语法:

    (parameters) -> expression

    (parameters) ->{ statements; }

    // 1. 不需要参数,返回值为 5

    () -> 5

    // 2. 接收一个参数(数字类型),返回其2倍的值

    x -> 2 * x

    // 3. 接受2个参数(数字),并返回他们的差值

    (x, y) -> x – y

    // 4. 接收2int型整数,返回他们的和

    (int x, int y) -> x + y

    // 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)

    (String s) -> System.out.print(s)

    2】基本的Lambda

    (1) 遍历集合

    String[] atp = {"Rafael Nadal", "Novak Djokovic",

           "Stanislas Wawrinka",

           "David Ferrer","Roger Federer",

           "Andy Murray","Tomas Berdych",

           "Juan Martin Del Potro"};

    List<String> players =  Arrays.asList(atp);

    // 以前的循环方式

    for (String player : players) {

         System.out.print(player + "; ");

    }

    // 使用 lambda 表达式以及函数操作(functional operation)

    players.forEach((player) -> System.out.print(player + "; "));

    // Java 8 中使用双冒号操作符(double colon operator)

    players.forEach(System.out::println);

    2)使用lambda来实现 Runnable接口

    // 1.1使用匿名内部类

    new Thread(new Runnable() {

        @Override

        public void run() {

            System.out.println("Hello world !");

        }

    }).start();

    // 1.2使用 lambda expression

    new Thread(() -> System.out.println("Hello world !")).start();

    // 2.1使用匿名内部类

    Runnable race1 = new Runnable() {

        @Override

        public void run() {

            System.out.println("Hello world !");

        }

    };

    // 2.2使用 lambda expression

    Runnable race2 = () -> System.out.println("Hello world !");

    // 直接调用 run 方法(没开新线程哦!)

    race1.run();

    race2.run();

    3)使用Lambda排序集合

    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));

        }

    });

    使用lambda可以通过下面的代码实现同样的功能

    // 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)));

    其他的排序如下所示。 和上面的示例一样,代码分别通过匿名内部类和一些lambda表达式来实现Comparator

    // 1.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(" "))));

        }

    });

    // 1.2 使用 lambda expression 排序,根据 surname

    Comparator<String> sortBySurname = (String s1, String s2) ->

        ( s1.substring(s1.indexOf(" ")).compareTo( s2.substring(s2.indexOf(" ")) ) );

    Arrays.sort(players, sortBySurname);

    // 1.3 或者这样,怀疑原作者是不是想错了,括号好多...

    Arrays.sort(players, (String s1, String s2) ->

          ( s1.substring(s1.indexOf(" ")).compareTo( s2.substring(s2.indexOf(" ")) ) )

        );

    // 2.1 使用匿名内部类根据 name lenght 排序 players

    Arrays.sort(players, new Comparator<String>() {

        @Override

        public int compare(String s1, String s2) {

            return (s1.length() - s2.length());

        }

    });

    // 2.2 使用 lambda expression 排序,根据 name lenght

    Comparator<String> sortByNameLenght = (String s1, String s2) -> (s1.length() - s2.length());

    Arrays.sort(players, sortByNameLenght);

    // 2.3 or this

    Arrays.sort(players, (String s1, String s2) -> (s1.length() - s2.length()));

    // 3.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));

        }

    });

    // 3.2 使用 lambda expression 排序,根据最后一个字母

    Comparator<String> sortByLastLetter =

        (String s1, String s2) ->

            (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1));

    Arrays.sort(players, sortByLastLetter);

    // 3.3 or this

    Arrays.sort(players, (String s1, String s2) -> (s1.charAt(s1.length() - 1) - s2.charAt(s2.length() - 1)));

    使用LambdaStream

    Stream是对集合的包装,通常和lambda一起使用。 使用lambdas可以支持许多操作,map, filter, limit, sorted, count, min, max, sum, collect 等等。 同样,Stream使用懒运算,他们并不会真正地读取所有数据,遇到像getFirst() 这样的方法就会结束链式语法。 在接下来的例子中,我们将探索lambdasstreams 能做什么。 我们创建了一个Person类并使用这个类来添加一些数据到list,将用于进一步流操作。

    Person 只是一个简单的POJO

    public class Person {

    private String firstName, lastName, job, gender;

    private int salary, age;

    public Person(String firstName, String lastName, String job,

                    String gender, int age, int salary)       {

              this.firstName = firstName;

              this.lastName = lastName;

              this.gender = gender;

              this.age = age;

              this.job = job;

              this.salary = salary;

    }

    // Getter and Setter

    // . . . . .

    }

    接下来,我们将创建两个list,都用来存放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));

      }

    };

    现在我们使用forEach方法来迭代输出上述列表:

    System.out.println("所有程序员的姓名:");

    javaProgrammers.forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));

    phpProgrammers.forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));

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

    System.out.println("给程序员加薪 5% :");

    Consumer<Person> giveRaise = e -> e.setSalary(e.getSalary() / 100 * 5 + e.getSalary());

    javaProgrammers.forEach(giveRaise);

    phpProgrammers.forEach(giveRaise);

    另一个有用的方法是过滤器filter() ,让我们显示月薪超过1400美元的PHP程序员:

    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("下面是年龄大于 24岁且月薪在$1,400以上的女PHP程序员:");

    phpProgrammers.stream()

              .filter(ageFilter)

              .filter(salaryFilter)

              .filter(genderFilter)

              .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));

    // 重用filters

    System.out.println("年龄大于 24岁的女性 Java programmers:");

    javaProgrammers.stream()

              .filter(ageFilter)

              .filter(genderFilter)

              .forEach((p) -> System.out.printf("%s %s; ", p.getFirstName(), p.getLastName()));

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

    System.out.println("最前面的3Java 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()));

    排序呢? 我们在stream中能处理吗? 答案是肯定的。 在下面的例子中,我们将根据名字和薪水排序Java程序员,放到一个list,然后显示列表:

    System.out.println("根据 name 排序,并显示前5Java 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()));

    如果我们只对最低和最高的薪水感兴趣,比排序后选择第一个/最后一个 更快的是minmax方法:

    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())

    上面的例子中我们已经看到 collect 方法是如何工作的。 结合 map 方法,我们可以使用 collect 方法来将我们的结果集放到一个字符串,一个 Set 或一个TreeSet:

    System.out.println("PHP programmers first name 拼接成字符串:");

    String phpDevelopers = phpProgrammers

              .stream()

              .map(Person::getFirstName)

              .collect(joining(" ; ")); // 在进一步的操作中可以作为标记(token)   

    System.out.println("Java programmers first name 存放到 Set:");

    Set<String> javaDevFirstName = javaProgrammers

              .stream()

              .map(Person::getFirstName)

              .collect(toSet());

    System.out.println("Java programmers first name 存放到 TreeSet:");

    TreeSet<String> javaDevLastName = javaProgrammers

              .stream()

              .map(Person::getLastName)

              .collect(toCollection(TreeSet::new));

    Streams 还可以是并行的(parallel)。 示例如下:

    System.out.println("计算付给 Java programmers 的所有money:");

    int totalSalary = javaProgrammers

              .parallelStream()

              .mapToInt(p -> p.getSalary())

              .sum();

    我们可以使用summaryStatistics方法获得stream 中元素的各种汇总数据。 接下来,我们可以访问这些方法,比如getMax, getMin, getSumgetAverage:

    //计算 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());

    lambda表达式取代了匿名内部类,取消了模板,允许程序猿用函数式风格编写代码,使代码可读性更高

    格式

    基本格式是:() -> {}

    有下面三种具体表达:

    (params) -> expression

    (params) -> statement

    (params) -> {statemen

    as里的配置

    要使用lambda,首先必须配置编译环境,这里使用的android studioas默认的jdk版本是1.6,修改成1.8即可使用,这里确保你系统安装了jdk1.8,否则需要用到下面插件:gradle-retrolambda

    as里的配置有两种方法:

    配置gradle脚本

    build.gradle脚本中添加下列代码:

    android {

       compileOptions {

           sourceCompatibility 1.8

           targetCompatibility 1.8

       }

    }

    当然写成下面的样子也是可以的

    android {

       compileOptions {

           sourceCompatibility JavaVersion.VERSION_1_8

           targetCompatibility JavaVersion.VERSION_1_8

       }

    }

    http://www.importnew.com/16436.html

  • 相关阅读:
    蓝书3.6 割点与桥
    蓝书3.5 强连通分量
    蓝书3.4 差分约束系统
    蓝书3.3 SPFA算法的优化
    蓝书3.2 最短路
    蓝书3.1 最小生成树
    luogu 4630 [APIO2018] Duathlon 铁人两项
    Codeforces Round #124 (Div. 1) C. Paint Tree(极角排序)
    dutacm.club Water Problem(矩阵快速幂)
    dutacm.club 1094: 等差区间(RMQ区间最大、最小值,区间GCD)
  • 原文地址:https://www.cnblogs.com/langfei8818/p/6151362.html
Copyright © 2020-2023  润新知