java1.8新特性(Lambda与方法引用)

java 8新特性

  • java 8 是java语言开发的一个主要版本, Oracle 公司于 2014 年 3 月 18 日发布 Java 8 ,它支持函数式编程,新的 JavaScript 引擎,新的日期 API,新的Stream API 等。

新特性

  • Lambda 表达式 是指允许把函数作为一个方法的参数(函数作为参数传递到方法中)
  • 方法引用 是指用提供了非常有用的语法,可以直接引用已有的java类或对象(实例)的方法或构造器。与Lambda联合使用,方法引用可以使语言的结构更加紧凑简介,减少冗余代码
  • 默认方法 是指方法就是一个在借口里面有了一个实现的方法
  • 新工具 新的编译工具,如:Nashorn引擎 jjs、 类依赖分析器jdeps。
  • Stream API 新添加的Stream API(java.util.stream) 把真正的函数式编程风格引入到Java中。
  • Date Time API 加强了对日期与时间的处理
  • Optional类 Optional类已经成为了java 8类库的一部分,用来解决空指针异常
  • Nashorn, JavaScript 引擎 − Java 8提供了一个新的Nashorn javascript引擎,它允许我们在JVM上运行特定的javascript应用。

1.Lambda 表达式

Lambda 表达式,也可以称为闭包,它是推动java8发布的重要特性。
Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)
使用Lambda表达式可以使代码变的更加简洁紧凑

语法

Lambda表达式的语法格式如下

(parameters) -> expression
或
(parameters) ->{ statements; }
以下是lambda表达式的重要特征
  • 可选类型声明:不需要声明参数类型,编译器可以统一识别参数值
  • 可选的参数圆括号:一个参数无需定义圆括号,但多个参数需要定义圆括号
  • 可选的大括号: 如果一个主体包含了一个语句,就不需要大括号
  • 可选的返回关键字:如果主体只有一个表达式返回值则编译器会自动返回值,大括号需要指定明表达式返回一个数值

Lambda 表达式简单例子

// 1. 不需要参数,返回值为 5  
() -> 5  

// 2. 接收一个参数(数字类型),返回其2倍的值  
x -> 2 * x  
  
// 3. 接受2个参数(数字),并返回他们的差值  
(x, y) -> x – y  
  
// 4. 接收2个int型整数,返回他们的和  
(int x, int y) -> x + y  
  
// 5. 接受一个 string 对象,并在控制台打印,不返回任何值(看起来像是返回void)  
(String s) -> System.out.print(s)

基本的Lambda例子

  • for 循环的写法

    @Test
    public void testLambda() {
        String[] strings = {"淘宝", "京东",
                "亚马逊", "谷歌", "百度", "美团",
                "天猫", "腾讯", "万达"};
        List<String> list = Arrays.asList(strings);
//        以前的循环形式
        for (String s : list) {
            System.out.print(s);
        }

// 使用 lambda 表达式以及函数操作(functional operation)
        System.out.println("");
        list.forEach((string) -> System.out.print(string + ";"));
        System.out.println("");
//        在java 8 中使用双冒号操作符(double colon operator)
        list.forEach(System.out::print);

    }

在这里插入图片描述
正如看到的,lambda表达式可以将我们的代码缩减到一行 ,同时Lambda的功能很强大 ,如实现Runnable接口的示例

//        使用匿名内部类
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello world 1.1");
            }
        }).start();


//      使用 lambda expression
        new Thread(() -> System.out.println("hello world 1.2")).start();


//        使用匿名内部类
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("hello world 2.1");
            }
        };
        Runnable r = () -> System.out.println("hello world 2.2");

        runnable.run();
        r.run();

在这里插入图片描述
Runnable 的 lambda表达式,使用块格式,将五行代码转换成单行语句

使用Lambda排序集合

在java中Comparator 类被用来排序集合,在下面的例子中 我们根据name,suname, name长度来进行排序

     String[] players = {"Rafael Nadal", "Novak Djokovic",
                "Stanislas Wawrinka", "David Ferrer",
                "Roger Federer", "Andy Murray",
                "Tomas Berdych", "Juan Martin Del Potro",
                "Richard Gasquet", "John Isner"};

//        使用匿名内部类来根据那么排序
        Arrays.sort(players, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
//                小于返回负数  相等返回0  大于返回正数
                return (o1.compareTo(o2));
            }
        });
//        使用lambdas,可以通过下面的代码实现同样的功能:
        Comparator<String> comparator = (String a1, String a2) -> (a1.compareTo(a2));
        Arrays.sort(players, comparator);

//        也可以使用下面的形式
        Arrays.sort(players, (String s1, String s2) -> (s1.compareTo(s2)));
//   同时使用lambda表达式的for循环
        List<String> list = Arrays.asList(players);
        list.forEach((string) -> System.out.print(string + ";"));
        System.out.println("");
        list.forEach(System.out::print);

在这里插入图片描述当然lambda表达式还有很多的用法 ,我只是在这里举例几个简单的例子

2.方法引用

  • 方法引用通过方法的名字来指向一个方法
  • 方法引用可以使语言的结构更加经凑,减少冗余代码
  • 方法引用使用一对冒号" : : "
  • 方法引用和lambda表达式一样 都是用来简化开发的

方法引用怎么使用

下来说一下方法引用使用到的操作符"::" ,这个操作符把方法引用分成两边,左边是类名或者某个对象的引用,右边是方法名或者是"new" (构造器引用是时用到)

以下三种引用

  • 引用方法
  • 引用构造器
  • 引用数组
    可以发现,方法引用可以引用的不止是方法,就像TCP/IP协议并不只有TCP/IP协议

引用方法

引用方法有下面几种形式

  • 对象应用::实例方法名
  • 类名::静态方法名
  • 类名::实例方法名

对象引用::实例方法名

有个函数式接口Consumer,里面有个抽象方法accept能够接收一个参数但是没有返回值,这个时候我想实现accept方法,让它的功能为打印接收到的那个参数,

Consumer<String> consumer = System.out::println;
consumer.accept("This is Major Tom");

System.out就是一个PrintStream类型的对象引用,而println则是一个实例方法名,需要注意的是没有括号的哟。其中Consumer是Java内置函数式接口,下面的例子用到的都是Java内置函数式接口。Consumer中的唯一抽象方法accept方法参数列表与println方法的参数列表相同,都是接收一个String类型参数

类名::静态方法名

//Function<Long, Long> f = x -> Math.abs(x);
Function<Long, Long> f = Math::abs;
Long result = f.apply(-3L);

Math是一个类而abs为该类的静态方法。Function中的唯一抽象方法apply方法参数列表与abs方法的参数列表相同,都是接收一个Long类型参数。

类名::实例方法名

//BiPredicate<String, String> b = (x,y) -> x.equals(y);
BiPredicate<String, String> b = String::equals;
b.test("abc", "abcd");

String是一个类而equals为该类的定义的实例方法。BiPredicate中的唯一抽象方法test方法参数列表与equals方法的参数列表相同,都是接收两个String类型参数。

方法引用实例

   List<String> list = new ArrayList<>();
        list.add("Google");
        list.add("Runoob");
        list.add("Taobao");
        list.add("Baidu");
        list.add("Sina");
        list.forEach(System.out::println);

猜你喜欢

转载自blog.csdn.net/qq_40688338/article/details/84536421