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

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

Lambda(λ)   -- 官网

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

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

Lambda表达式:

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

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

@FunctionalInterface
public 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表达式分为了三个方面来阐述,官方地址

方法引用,示例:

先建一个实体类:

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方法那样,从而多个不同的操作可以在一个语句里串起来。示例:

@Test
public 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 计数





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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值