JDK8新特性

一、Lambda表达式

什么是Lambda

 Lambda表达式是JDK 8开始新增的一种语法形式;

作用:

用于简化匿名内部类的代码写法。

注意 :  Lambda表达式只能简化函数式接口的匿名内部类!!!

什么是函数式接口?

有且仅有一个抽象方法的接口

注意:将来我们见到的大部分函数式接口,上面都可能会有一个@FunctionalInterface的注解,有该注解的接口就必定是函数式接口。

Lambda表达式的标准格式

组成Lambda表达式的三要素:

形参列表、箭头、代码块

(被重写方法的形参列表) -> {
  
   被重写方法的方法体代码。
}

Snipaste_2022-05-11_22-59-22.png

 

/*
    目标:掌握Lambda表达式的格式

    小结:
        1.Lambda表达式的作用
        (参数列表) -> {方法体}

        2.Lambda表达式的组成格式
 */
public class Demo1 {

    public static void main(String[] args) {
        test(new A() {
            @Override
            public void show() {
                System.out.println("匿名内部类的实现");
            }
        });

        //Lambda表达式:简化匿名内部类
        test( () ->{
            System.out.println("匿名内部类的实现");
        } );

    }

    //自定义方法
    public static void test(A a){
        a.show();
    }
}

@FunctionalInterface //标记该接口是函数式接口(有且只有一个抽象方法),函数式接口使用时可以使用Lambda表达式替换
interface A{
    void show();
}

Lambda表达式的省略规则

Lambda思想:可推导的就可省略,只保留方法要执行的核心代码

省略规则:
➢ 参数类型可以省略。
比如(Integer o1, Integer o2) 省略后 (o1, o2)
➢ 如果参数有且仅有一个参数类型和小括号都可以省略。
比如(String s) 省略后 s
➢ 如果代码块的语句只有一条,可以省略大括号,分号和return

Snipaste_2022-05-11_23-02-12.png

 

二、方法引用

方法引用是java8的新特性之一, 可以直接引用已有Java类或对象的方法或构造器。方法引用与
Lambda表达式结合使用,可以进一步简化代码。

方法引用格式

1.静态方法的引用: 类名::静态方法

使用场景:

如果某个Lambda表达式里只是调用一个静态方法,并且前后参数的形式一致,就可以使用静态方法引用。

2.实例方法的引用: 对象名::实例方法

使用场景:

如果某个Lambda表达式里只是调用一个实例方法,并且前后参数的形式一致,就可以使用实例方法引用。

3.特定类型的方法引用:类型::方法

使用场景:

如果某个Lambda表达式里只是调用一个实例方法,并且前面参数列表中的第一个参数是作为方法的主调,后面的所有参数都是作为该实例方法的入参的,则此时就可以使用特定类型的方法引用。

4.构造器引用:类名::new

使用场景:

如果某个Lambda表达式里只是在创建对象,并且前后参数情况一致,就可以使用构造器引用。

方法引用前提

1. Lambda表达式中仅仅调用了一个方法。
2. 调用的方法与要实现的抽象方法的参数和返回值一致时,可以使用方法引用代替

/*
匿名内部类的抽象方法中仅仅调用了一个方法。
调用的方法与要实现的抽象方法的参数和返回值一致时,可以使用方法引用代替。
 */
public class Demo {

    public static void main(String[] args) {

      /*  Date date = new Date();
        printTime(new TimeUtil() {
            @Override
            public long showTime() {
                return date.getTime(); //getTime方法去代替了抽象的showTime方法
            }
        });
        //方法引用
        //引用了date对象的getTime,去实现了接口的抽象方法(移花接木)
        printTime(date::getTime);*/

        printTime(new TimeUtil() {
            @Override
            public long showTime() {
                return System.currentTimeMillis();
            }
        });

        //方法引用代替showTime的功能(静态方法引用)
        printTime(System::currentTimeMillis);

    }

    public static void printTime(TimeUtil tn) {
        long time = tn.showTime();
        System.out.println(time);
    }
}

@FunctionalInterface
interface TimeUtil {
    //获取毫秒值
    long showTime();
}

三、Stream流

Stream流概述

也叫Stream流,是Jdk8开始新增的一套API (java.util.stream.*)可以用于操作集合或者数组的数据。Stream流相当于工厂里面的流水线,提供了丰富的API,方便对数据进行加工处理。

优势: Stream流大量的结合了Lambda的语法风格来编程,提供了一种更加强大,更加简单的方式操作集合或者数组中的数据,代码更简洁,可读性更好

Stream流操作步骤

获取Stream流
创建一条流水线,并把数据放到流水线上准备进行操作。
中间方法
流水线上的操作,一次操作完毕之后,还可以继续进行其他操作。
终结方法
是流水线上的最后一个操作,一个Stream流只能有一次终结方法。

Snipaste_2022-05-11_23-15-57.png

 

使用注意事项

1、创建Stream流

方式1:根据集合获取流 ——针对于集合
Collection根接口中提供了 stream( ) 方法可以获取流。
单列集合:直接调用stream()方法即可。
双列集合:先获取键和值的单列集合,再通过集合获取键和值各自的Stream流。

方式2:根据Arrays工具类方法获取流 ——针对于数组

Arrays类提供了静态的stream(T[] array)方法可以获取流。

方式3:根据of方法获取流——针对于其他数据类型
Stream类提供了静态的 of( ) 方法,可以创建一个流对象。
Stream.of(T ... values)

public class demo04 {
    /*
    目标:掌握获取Stream流的3种方式

    小结:
        方式1:根据集合对象获取流
            单列集合: 集合对象.stream()

            双列集合:
                先获取键的集合,在通过键的集合获取流
         
         方式2:根据Arrays工具类获取流
             Arrays.stream(T[] array)

        方式3:根据of方法获取流
            static <T> Stream<T> of(T... values)

 */
    public static void main(String[] args) {

        ArrayList<Integer> list = new ArrayList<>();
        Stream<Integer> stream = list.stream();

        // Map集合
        HashMap<Integer, Integer> map = new HashMap<>();
        // 先单独获取键 或者 值的 集合
        Set<Integer> set = map.keySet();
        Stream<Integer> stream1 = set.stream();

        // 值集合————使用Collection中的vlaus方法,获取map中的值集合。
        Collection<Integer> values = map.values();
        Stream<Integer> stream2 = values.stream();

        // 针对于数组,字符串等
        Integer[] arr = {11, 22, 33, 44};
        Stream<Integer> stream3 = Arrays.stream(arr);
        Stream<String> stream4 = Stream.of("abc", "defa");
    }
}

2、常用方法

中间方法指的是调用完成后会返回新的stream流,可以继续使用【支持链式编程】

 终结方法指的是调用完成后,不会返回新的Stream了,无法继续使用流了

 注意:sorted()默认是升序的,使用自定义类型时要指定排序规则

public class demo02 {
    public static void main(String[] args) {
        // 需求:定义一个学生类【类中包含 姓名,成绩】,定义6个学生对象,添加到集合中
        List<Student> list = new ArrayList<>();
        Collections.addAll(list,
                new Student("张三",100.0),
                new Student("李四",66.6),
                new Student("张三",100.0),
                new Student("王五",88.0),
                new Student("赵六",99.9)
        );
        // 实现下面的功能:实现学生的去重【如果学生对象名字和成绩相同,则认为是同一个人】,
        // 把学生中成绩及格的同学找出,然后成绩按照升序排序,  跳过前2个学生,
        list.stream().distinct().filter(student -> {
            return student.getScore() >= 60.0;
        }).sorted((s1,s2) -> {
            return Double.compare(s1.getScore(), s2.getScore());
        }).skip(2).forEach(System.out::println);
        // 最后把符合条件的学生的名字找出,输出结果
    }
}

public class Student {
    //重写hashCode()和equals()
    //认为学生对象名字和成绩相同,则认为是同一个
    //配合distinct()使用

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Double.compare(student.score, score) == 0 && Objects.equals(name, student.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, score);
    }
}

3、注意事项

⚫ 一个Stream流对象只能操作一次。
⚫ 调用中间方法会返回新流,以便下次操作使用。
⚫ 终结方法如果没调用,中间方法也不会执行,表示该流还没有操作,可以拿到返回值。

4、流的收集

收集Stream流:就是把Stream流操作后的结果转回到集合或者数组中去返回

Stream流:方便操作集合/数组的手段;   集合/数组:才是开发中的目的

 

 

public class Demo {
    /*
        目标:能够把Stream对应转化 集合 / 数组
     */
    public static void main(String[] args) {
        // 定义6个学生对象
        Student s1 = new Student("张三", 100);
        Student s2 = new Student("李四", 48);
        Student s3 = new Student("王五", 95);
        Student s4 = new Student("赵六", 88);
        Student s5 = new Student("田七", 90);
        // 添加到集合中
        ArrayList<Student> list = new ArrayList<>();
        Collections.addAll(list, s1, s2, s3, s4, s5);
        // 筛选出考试前三面的同学,收集成一个List
        List<Student> list1 = list.stream()
                .sorted((o1, o2) -> {
                    return Double.compare(o2.getScore(), o1.getScore());
                })
                .limit(3)
                .collect(Collectors.toList());
        System.out.println(list1);
        System.out.println("-------------------------------");
        // 筛选出考试前三面的同学,收集成一个Set
        Set<Student> set = list.stream()
                .sorted((o1, o2) -> {
                    return Double.compare(o2.getScore(), o1.getScore());
                })
                .limit(3)
                .collect(Collectors.toSet());
        System.out.println(set);

        System.out.println("-------------------------------");
        // 把学生的名字和成绩 组成一个Map
      /*  Map<String, Double> map = list.stream()
                .collect(Collectors.toMap(new Function<Student, String>() {
                                              @Override
                                              public String apply(Student student) {
                                                  return student.getName();
                                              }
                                          },
                                new Function<Student, Double>() {
                                    @Override
                                    public Double apply(Student student) {
                                        return student.getScore();
                                    }
                                })

                );
        System.out.println(map);*/
        Map<String, Double> map2 = list.stream()
                .collect(Collectors.toMap(k -> k.getName(), v -> v.getScore()));
        System.out.println(map2);
        System.out.println("-------------------------------");
        // 把stream收集为一个数组
        Object[] array = list.stream().toArray();
        System.out.println(Arrays.toString(array));

    }
}
/*
    已知两个集合数据:
        第一个队伍数据:"令狐冲", "风清扬", "任我行", "东方不败", "岳不群" Stream.of()
        第二个队伍数据:"马云", "李彦宏", "刘强东", "马化腾", "马保国" Stream.of()

    要求:
        第一个队伍只要名字为3个字的姓名。filter()
        第一个队伍筛选之后只要前3人。limit()

        第二个队伍只要姓马的姓名。startsWith("马")
        第二个队伍不要前2人。skip()

        将两个队伍合并到一个队伍  concat(流1,流2)
        根据姓名创建Person对象, map()
        存储到一个新集合。 collect()
        遍历集合 forEach()

     使用Stream流式编程完成
 */
public class Demo1 {

    public static void main(String[] args) {

        Stream<String> s1 = Stream.of("令狐冲", "风清扬", "任我行", "东方不败", "岳不群").filter(s -> s.length() == 3).limit(3);


        Stream<String> s2 = Stream.of("马云", "李彦宏", "刘强东", "马化腾", "马保国").filter(s -> s.startsWith("马")).skip(2);

        //将两个队伍合并到一个队伍,根据姓名创建Person对象
       /* Stream.concat(s1,s2).map(new Function<String, Person>() {
            @Override
            public Person apply(String s) {
                return new Person(s);
            }
        });*/

        Stream.concat( s1, s2).map(Person::new).collect(Collectors.toList()).forEach(System.out::println);


        //一行代码(不建议)
       //Stream.concat( Stream.of("令狐冲", "风清扬", "任我行", "东方不败", "岳不群").filter(s -> s.length() == 3).limit(3), Stream.of("马云", "李彦宏", "刘强东", "马化腾", "马保国").filter(s -> s.startsWith("马")).skip(2)).map(Person::new).collect(Collectors.toList()).forEach(System.out::println);

    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值