JDK 8新特性学习之Lambda表达式

来源:互联网 发布:兵棋推演软件 编辑:程序博客网 时间:2024/06/08 00:32

JDK8发布已经有很长的一段时间了,以前就简单了解就没继续了解,今天抽空整理了一下,欢迎更正补充。JDK8新特新之一:

Lambda(λ)   -- 官网

Lamda实际上就是一个匿名方法, 实例:

@Testpublic void oldRunable() {    new Thread(new Runnable() {        @Override        public void run() {            System.out.println("The old runable now is using!");        }    }).start();}

Lambda表达式:

@Testpublic void runable() {    new Thread(() -> System.out.println("It's a lambda function!")).start();}

Lambda的类型叫做“目标类型(Target Type)”,它的目标是“函数接口(Functional Interface)”,这是JDK8引入的概念。它的定义是:一个接口,如果只有一个显式声明的抽象方法,那么他就是一个函数接口,一般用@FunctionalInterface标注出来(也可以不标)。示例:

@FunctionalInterfacepublic interface Runnable { void run(); }public interface Callable<V> { V call() throws Exception; }public interface ActionListener { void actionPerformed(ActionEvent e); }public interface Comparator<T> { int compare(T o1, T o2); boolean equals(Object obj); }
注意上面Comparator接口虽然声明了2个接口,但他就是函数接口。这是因为equals方法时Object的,所有的接口都会声明Object的public方法(隐式)的,所以它还是一个函数接口。

Lambda表达式分为了三个方面来阐述,官方地址:

  • 方法引用:(Method Reference)
  • 默认方法:(Default Method)
  • 新的Lambda表达式和流的新增和增强API(New and Enhanced APIs That Take Advantage of Lambda Expressions and Streams in Java SE 8)

方法引用,示例:

先建一个实体类:

class Person{    @Getter    Integer age;    @Getter    String name;    @Getter    String firstName;    Person(Integer age){        this.age = age;    }    Person(Integer age, String name){        this.age = age;        this.name = name;    }    Person(String name, String firstName, Integer age){        this.name = name;        this.firstName = firstName;        this.age = age;    }    public static int compare(Person a, Person b){        return a.getAge().compareTo(b.getAge());    }}

示例:

    @Test    public void test(){        // list 排序        ArrayList<Person> list = new ArrayList<>();        list.add(new Person(30));        list.add(new Person(40));        list.add(new Person(10));        System.out.println(list);        list.forEach(a->{System.out.println(a.getAge());});//        list.sort((a,b)-> b.getAge().compareTo(a.getAge())); // 方法引用        list.sort(Comparator.comparing(Person::getAge)); // 对象方法引用        System.out.println(list);        // 数组排序        Person[] people = new Person[]{                new Person("name1", "f1", 20),                new Person("name2", "u2",30),                new Person("name3", "p3",10),                new Person("name4R", "r4",60),        };        for(Person p : people){            System.out.println(p.getAge());        }        System.out.println("             --       ");        // 方法一//        Arrays.sort(people, (a,b)->  a.getAge().compareTo(b.getAge())); // 方法引用        // 方法二//        Arrays.sort(people, (a, b) -> Person.compare(a,b)); // 对象方法引用        // 方法三//        Arrays.sort(people, Person::compare); // 静态对象方法引用(对象方法必须为静态)//        for(Person p : people){//            System.out.println(p.getAge());//        }        Arrays.sort(people, Comparator.comparing(Person::getFirstName)); // 对象方法引用        for (Person p: people){            System.out.println(p.getFirstName());        }    }

官方文档还写了一种构造器方法引用,示例:

public class LambdaTest {    // 构造器引用    public static    <T, SOURCE extends Collection<T>, DEST extends Collection<T>> DEST transfer(        SOURCE source, Supplier<DEST> collectionFactory    ){        DEST result = collectionFactory.get();        for (T t : source) {            result.add(t);        }        return result;    }
    @Test    public void test1(){
        ArrayList<Person> list = new ArrayList<>();
list.add(new Person(40)); list.add(new Person(10)); System.out.println(list); list.forEach(a->{System.out.println(a.getAge());}); Set<Person> personSet = transfer(list, ()->new HashSet<>()); System.out.println(personSet); // 构造器引用转换-方法引用 personSet = transfer(list, HashSet::new); System.out.println(personSet); // 构造器引用转换-静态引用 list.add(new Person(99)); // 检验对象是否变化 personSet = transfer(list, HashSet<Person>::new); System.out.println(personSet); // 构造器引用转换-泛型静态引用 }
}

另外附加一个lambda对象的创建方式:

new HashSet();  ==   HashSet::new   ==   HashSet<Person>::new


默认方法引用,有两种方式:

  • 引用实现,在引用一个方法时,需要对这个方法设定默认值,则需要在这个方法上加一个修饰符 default 并附加实现方法。或者创建一个接口实现原接口,然后实现新接口并实现接口方法。
  • 静态共享(一个静态方法是一个与它定义的类相关联的方法,而不是与任何对象相关联,每个类的实例共享其静态方法)

详情请查看官网文档。


流的使用

Java8为集合类引入了另一个重要概念:流(stream)。一个流通常以一个集合类实例为其数据源,然后在其上定义各种操作。流的API设计使用了管道(pipelines)模式。对流的一次操作会返回另一个流。如同IO的API或者StringBuffer的append方法那样,从而多个不同的操作可以在一个语句里串起来。示例:

@Testpublic void test2(){    // list 排序    ArrayList<Person> list = new ArrayList<>();    list.add(new Person("name1", "f1", 20));    list.add(new Person("name2", "u2",30));    list.add(new Person("name3", "p3",10));    list.add(new Person("name4R", "r4",60));    System.out.println(list);    list.forEach(a->{System.out.println(a.getAge());});    // 流的使用    List newL = list.stream().filter(a -> a.getFirstName().equals("test1")).distinct().collect(Collectors.toList());    System.out.println(newL);    newL = list.stream().map(a -> Integer.valueOf(a.getAge())).filter(a -> a>20).collect(Collectors.toList());    System.out.println(newL);    newL.forEach(a->{System.out.println(a);});}

个人流的使用小结:

.stream 转化为流的方式, 用法:list.stream
.map 遍历,用法:.map(m -> new Integer(m))
.filter  拦截器,用法:.filter(a -> a.getA == a)
.forEach  遍历,forEachordered较之比较稳定,顺序执行, 用法: .forEach(a -> System.out.println(a);)
.distinct  去重, 用法:list.stream.distinct()
.collect  收集结果, 用法: .collect(Collectors.toList());
.toArray  转化成数组
.reduce  返回单个结果值(执行层,每次处理一个元素创建一个新值),用法:.reduce(a)
.sorted  排序
.findFirst 查询第一个元素并输出
.findAny  返回任何一个元素,并返回Optional实例
.flatmap  将包含通过映射函数替换源流的每个元素而获得的元素,并使结果平坦化
.limit  限制最大数量值
.max  获取最大值,min反之
.peek  中间操作流,返回一个新流
.skip  从开始的流对象中跳过给定数量的元素
.allMatch  全匹配,匹配成功返回true。同理有anyMatch,noneMatch
.count 计数



 
原创粉丝点击