Java 中Lambda表达式基本用法

JDK8引入的Lambda表达式在简化程序代码方面大显身手,在程序遍历访问集合中元素的场合,运用Lambda表达式可以大大简化操纵集合的程序代码。他本质只是一颗让编程人员更加得心用手的“语法糖”。下面引入实例介绍Lambda的应用场景:

1、Lambda表达式的基本用法(遍历访问List列表)

        List<String> list = new ArrayList<>();
        Collections.addAll(list,new String[]{"Tome","Make","Jike","Honey"});
        //传统的List遍历集合
        for(String name : list){
            System.out.print(name+",");
        }
        //方式二:使用Lambda表达式
        list.forEach((String name)->{ System.out.print(name+","); });
        //方式三:在 Java 8 中使用双冒号操作符 
        list.forEach(System.out::print);

比较3种遍历集合的代码,不难发现,使用Lambda表达式可以简化程序代码,Lambda的基本语法为:

(Type1 param1,Type2 param2,...,TypeN paramN)->{

      statment1;

      statment2;

                 return statmentM

}

Lambda表达式在某些条件下可以再简化:

(1)、参数类型可以省略。在绝大多数情况下,编译器都可以从上下文中聪明的推断出Lambda表达式的参数类型,对于以上的Lambda表达式,编译器能推断出name变量的类型为String,因此Lambda表达式可以简化为:

list.forEach((name)->{ System.out.print(name+","); });

(2)、当Lambda表达式的参数个数只有一个时,可以省略小括号。以上Lambda表达式可以简化为:

 list.forEach(name->{ System.out.print(name+","); });

(3)、当Lambda表达式只包含一条语句时,可以省略大括号、语句结尾的分号,此外,当return语句没有返回值时也可以省略。

 list.forEach(name-> System.out.print(name+","));

(4)、Lambda表达式中符号“->”后面也可以包含一个普通的表达式,语法为:

(Type1 param1,Type2 param2,...,TypeN paramN)->(expression)

例如:( int a,int b) -> (a*b+2)

2、Lambda表达式中的方法引用

上述代码方法三中“::”符是因为在编译器能根据上下文来推断Lambda表达式的参数的场合,可以在Lambda表达式中省略参数,直接通过“::”符号来引用方法。方法引用的语法格式有以下3中:

第一种方式:objectName::instanceMethod //引用实例方法

第二种方式: ClassName::staticMethod      //引用静态方法

第三种方式: ClassName::instanceMethod //引用实例方法

下面举例说明:

x-> System.out.println(x)  等同于:   System.out::println;    //引用实例方法

(x,y)->Math.max(x,y)        等同于:   Math::max                  //引用静态方法

x->x.toLowerCase()          等同于:   String::toLowerCase //引用实例方法

3、用Lambda表达式代替内部类

         //一、使用匿名内部类
         new Thread(new Runnable() {
            public void run() {
                System.out.println("Runnable Implement By Anonymous Inner Class");
            }
        }).start();
         //二、使用Lambda表达式
        new Thread(()->System.out.println("Runnable Implement By Lambda")).start();
        //三、使用Lambda表达式
        Runnable runnable = ()->{ System.out.println("Runnable Implement"); };
        new Thread(runnable).start();

方式二和方式三的Lambda表达式相当于创建了实现Runnable接口的匿名对象;由于Runnable接口的run()方法不带参数,因此,Lambda表达式的参数列表也相应为空“()”,Lambda表达式中符号“->”后面的可执行语句块相当于run()方法的方法体。

4、用Lambda表达式对集合进行排序

        List<String> list = new ArrayList<>();
        Collections.addAll(list,new String[]{"Tome","Make","Jike","Honey"});
        //方式一:通过创建匿名的Comparator实例来排序
        Comparator<String> cp = new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return  (o1.compareTo(o2));
            }
        };
        Collections.sort(list,cp);
        //方式二:用Lymbda表达式来排序
        Comparator<String> comparator =(String name1,String name2)->        (name1.compareTo(name2));
        Collections.sort(list,comparator);
        //方式三:用Lymbda表达式来排序
        Collections.sort(list,(String name1,String name2)->(name1.compareTo(name2)));

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

以上方式二和方式三的Lambda表达式相当于创建了Comparator类型的匿名对象,由于Comparator接口的

compare(T name1,T name2)方法有两个参数,所以Lymbda表达式也有两个相应的参数(String name1,String name2),Lambda 表达式中符号“->” 后面的表达式“name1.compareTo(name2)”相当于compare(T name1,T name2)方法的方法体。

5、Lambda表达式与Steam联合使用

从JDK8开始,专门抽象出了java.util.stream.Stream流接口,他可以充当Java集合的适配器,使得程序能够按照操纵流的方式来访问集合中的元素

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

Person.java:

package lambda;
public class Person {
    private String name;
    private int age;
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}

创建一个包含Person对象的ArrayList列表,接着调用他的stream()方法得到一个流,接着再对流中的元素进行过滤和排序等操作。

LambdaForCollectionAction.java:

package lambda;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class LambdaForCollectionAction {
    public static void main(String[] args) {
        List<Person> persons = new ArrayList<Person>();
        Collections.addAll(persons,
                new Person("Jack",20),
                new Person("Jack",25),
                new Person("Mike",30),
                new Person("Mary",19),
                new Person("Sun",29));
        persons.stream()
                .filter(p ->p.getAge()>20) //过滤条件为年龄大于20
                .forEach(p -> System.out.println(p.getName()+":"+p.getAge()));

        persons.stream()
                .sorted((p1,p2)->(p1.getAge()-p2.getAge()))//按照年龄排序
                .limit(3)           //取出3个元素
                .forEach(p -> System.out.println(p.getName()+":"+p.getAge()));

        int maxAge = persons.parallelStream()//获得并行流
                //把包含Person对象的流映射为保存其age属性的int类型流
                .mapToInt(p->p.getAge())
                .max()
                .getAsInt();
        System.out.println("Max Age :"+maxAge);
    }
}

在ColTester类的main()方法中,persons.stream()方法返回一个Stream对象,接下来调用Stream对象的filter(),sort()和forEach()方法时,传入的都是Lymbda表达式,Stream接口的filter()方法的完整声明为:

 /**
     * Returns a stream consisting of the elements of this stream that match
     * the given predicate.
     *
     * <p>This is an <a href="package-summary.html#StreamOps">intermediate
     * operation</a>.
     *
     * @param predicate a <a href="package-summary.html#NonInterference">non-interfering</a>,
     *                  <a href="package-summary.html#Statelessness">stateless</a>
     *                  predicate to apply to each element to determine if it
     *                  should be included
     * @return the new stream
     */
    Stream<T> filter(Predicate<? super T> predicate);

以上filter()方法有一个Predicate类型的参数,用来指明过滤数据的条件。Predicate接口的 boolean test(T t);方法判断参数t是否符合过滤条件,如果符合就返回true,否则就返回false。以上程序代码“filter(p ->p.getAge()>20)” 通过Lambda表达式创建了一个Predicate匿名对象,把他传给filter()方法。Lymbda表达式中"->"后面的表达式"p.getAge()>20"相当于是test(T t)方法的方法体。

Collection接口的parallelStream()方法返回一个采用并行处理的Stream对象,当集合中有大量数据时,为了提高处理集合中元素的效率,可以调用此方法来得到Stream对象,它的内部实现会开启多个线程来并发处理数据。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值