Java Lambda表达式——Java 8 新特性

lambda表达式简介:(本质是一个“语法糖”)

Lambda表达式是Java SE 8中一个重要的新特性。lambda表达式允许你通过表达式来代替功能接口。 lambda表达式就和方法一样,它提供了一个正常的参数列表和一个使用这些参数的主体(body,可以是一个表达式或一个代码块)。
Lambda表达式还增强了集合库。 Java SE 8添加了2个对集合数据进行批量操作的包: java.util.function 包以及 java.util.stream 包。 流(stream)就如同迭代器(iterator),但附加了许多额外的功能。 总的来说,lambda表达式和 stream 是自Java语言添加泛型(Generics)和注解(annotation)以来最大的变化。

Lambda表达式语法:

基本语法:
(paramets)->expression
或:
(parameter)-> (statement)

匿名类型的最大问题就在于其冗余的语法。有人戏称匿名类型导致了“高度问题”。而java API中可以使用匿名类型把行为内联,对接口进行实现,不必专门定义一个类。
例如:

public interface ActionListener {
  void actionPerformed(ActionEvent e);
}

这里并不需要专门定义一个类来实现 ActionListener,因为它只会在调用处被使用一次。用户一般会使用匿名类型把行为内联(inline):

button.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent e) {
    ui.dazzle(e.getModifiers());
  }
});
匿名内部类的缺点:
  1. 语法过于冗余
  2. 匿名类中的this
  3. 类型载入和实例创建语义不够灵活
  4. 无法捕获非final的局部变量
  5. 无法对控制流进行抽象

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 表达式接收 x 和 y 这两个整形参数并返回它们的和;第二个 lambda 表达式不接收参数,返回整数 ‘42’;第三个 lambda 表达式接收一个字符串并把它打印到控制台,不返回值。

lambda表达式的语法由参数列表,箭头符号->和函数体组成。函数体即可以是一个表达式,也可以是一个语句块。

  • 表达式:表达式会被执行,然后返回一个执行结果。
  • 语句块:语句块中的语句会被执行,就先方法中的语句一样——
    - return 语句会把控制权交给匿名方法的调用者
    - break 和continue只能在循环体中使用
    - 如果函数有返回值,name函数体内部的每一条路径都必须返回值。

表达式函数体适合小型 lambda 表达式,它消除了 return 关键字,使得语法更加简洁。

lambda 表达式也会经常出现在嵌套环境中,比如说作为方法的参数。为了使 lambda 表达式在这些场景下尽可能简洁,我们去除了不必要的分隔符。不过在某些情况下我们也可以把它分为多行,然后用括号包起来,就像其它普通表达式一样。

public class lambda_demo {
    public void lambda0()
    {
        String []atp = {"Rafael Nadal", "Novak Djokovic",
                "Stanislas Wawrinka",
                "David Ferrer","Roger Federer",
                "Andy Murray","Tomas Berdych",
                "Juan Martin Del Potro"};
        List<String> asList = Arrays.asList(atp);
        //以前的循环方式
        for(String s :asList)
        {
            System.out.println(s+" : ");
        }

        // 使用 lambda 表达式以及函数操作(functional operation)
        asList.forEach((s) -> System.out.println(s + ":"));

        // 在 Java 8 中使用双冒号操作符(double colon operator)
        //asList.forEach(System.out::print);
        asList.forEach(System.out::println);       

    }

    public static void main(String []args)
    {
        lambda_demo demo = new lambda_demo();
        demo.lambda0();
    }
}
双冒号操作符(方法引用)

双冒号操作符详细介绍
形如ClassName::methodName 或者 ObjectName:: methodName 的表达式。为方法表达式。

方法引用的种类

方法引用有四种,分别是:

  • 指向静态方法的引用
  • 指向某个对象的实例方法的引用
  • 指向某个类型的实例方法的引用
  • 指向构造方法的引用

lambda语法代码非常的简洁。也可以用来实现Runnable接口。

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

        //1.2使用lambda表达式
        Runnable  racel = new Runnable() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        };

        //1.3使用lambda表达式,更简洁方式
        Runnable race2 = ()-> System.out.println("hello");

        //这里直接调用lambda表达式。直接调用run方法,没开新线程。
        racel.run();
        race2.run();

下面列举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));
            }
        });

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

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

参考链接

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值