天天看点

JDK8新特性简介、Lambda表达式、Stream流常用api介绍JDK8新特性简介、Lambda表达式、Stream流常用api介绍

JDK8新特性简介、Lambda表达式、Stream流常用api介绍

接口

  1. Java1.8前接口中是不允许有普通方法的,在Java1.8后允许接口中有普通方法,只需要加上default关键字即可;
  2. Java1.8后可以使用static和default修饰方法后,可以存在方法体。

代码 

public interface UserService {
    /**
     * 新增
     * @param name 用户名
     * @param age 年龄
     */
    void insert(String name,Integer age);

    /**
     * 更新
     * @param name
     * @return
     */
    default String update(String name){
        return "success";
    }

    /**
     * 查询
     * @return
     */
    static String select(){
        System.out.println("五月天");
        return "加入五月天永远不会太迟";
    };
}
           

函数式接口

接口中只定义了唯一一个自定义的抽象方法,此接口就可以默认称作函数接口

实现方式:

  1. 在接口中定义唯一 一个自定义的抽象方法;
  2. 使用@FunctionInterface注解:目的是为了强制接口只有唯一一个抽象方法,可以存在static、default修饰的普通方法。
public static void main(String[] args) {
   UserService userService=new UserService(){
       @Override
       public void insert(String name,Integer age){
           System.out.println("name:"+name+"...........age:"+age);
       }
   };
   userService.insert("命硬",22);
}
           
UserService userService1 = (name, age) -> {
    System.out.println("name:" + name + "..............age" + age);
};
userService1.insert("命硬", 22);
           

使用Lambda简化匿名内部类

public static void main(String[] args) {
    /**
     * 使用匿名内部类实现线程
     *
     * @param
     * @return void
     * @time: 2020/1/16 16:28
     */
    Runnable runnable=new Runnable(){
        @Override
        public void run() {
            System.out.println("主线程名称:"+Thread.currentThread().getName());
        }
    };
    new Thread(runnable).start();

    /**
     * 使用Lambda简化匿名内部类
     *
     * @param
     * @return void
     * @time: 2020/1/16 16:29
     */
    new Thread(()->{
        System.out.println("主线程名称:"+Thread.currentThread().getName());
    });


}
           

遍历集合的三种方式:

ArrayList<String> list = new ArrayList<>();
 list.add("小彪子");
 list.add("小鹏子");
 list.add("小康子");
 /**
  * 使用匿名内部类遍历集合
  *
  * @param
  * @return void
  * @time: 2020/1/16 16:47
  */
 System.out.println("使用匿名内部类遍历集合");
 list.forEach(new Consumer<String>() {
     @Override
     public void accept(String s) {
         System.out.println(s);
     }
 });

 /**
  *
  * 使用Lambda表达式遍历集合
  *
  * @param
  * @return void
  * @time: 2020/1/16 16:51
  */
 System.out.println("使用Lambda遍历集合");
 list.forEach((t) -> {
     System.out.println(t);
 });


 /**
  *
  * 使用方法引用形式遍历集合
  * @param
  * @return void
  * @time: 2020/1/16 16:53
  */
 System.out.println("使用方法引用形式遍历集合");
 list.forEach(System.out::println);
           

运行结果:

JDK8新特性简介、Lambda表达式、Stream流常用api介绍JDK8新特性简介、Lambda表达式、Stream流常用api介绍

方法引入

静态方法引入

@FunctionalInterface
public interface FunctionInterfaceTest {
    void test();
}
           
public class Test {
    public static void main(String[] args) {
        /** 静态方法引入 */
        System.out.println("****静态方法引入***");
//        FunctionInterfaceTest functionInterfaceTest1=()->Test.test();
        FunctionInterfaceTest functionInterfaceTest2 = Test::test;
        functionInterfaceTest2.test();
    }

    public static void test(){
        System.out.println("静态方法引入");
    }
}
           

 注意:静态方法引入的静态方法需要和函数式接口的参数和返回类型一致。实例方法引入和静态方法遵循引入相同规则。

实例方法引入

@FunctionalInterface
public interface FunctionInterfaceTest {
    String test();
}
           
public class Test {
    public static void main(String[] args) {
        System.out.println("****实例方法引入***");
        Test test = new Test();
        FunctionInterfaceTest functionInterfaceTest1=()->test.sing();
        FunctionInterfaceTest functionInterfaceTest2 = test::sing;
        System.out.println(functionInterfaceTest1.test());
        System.out.println(functionInterfaceTest2.test());
    }

    public String sing(){
        return "五月天唱了一首《突然好想你》!";
    }
}
           

运行结果:

JDK8新特性简介、Lambda表达式、Stream流常用api介绍JDK8新特性简介、Lambda表达式、Stream流常用api介绍

注意:若函数接口的参数和实例对象是一个对象则无需实例化对象。

@FunctionalInterface
public interface FunctionInterfaceTest {
    String test(Test test);
}
           
public class Test {
    public static void main(String[] args) {
//      FunctionInterfaceTest functionInterfaceTest =(test)->test.sing();
        FunctionInterfaceTest functionInterfaceTest =Test::sing;
    }

    public String sing(){
        return "五月天唱了一首《突然好想你》!";
    }
}
           

构造函数引入 

@FunctionalInterface
public interface FunctionInterfaceTest {
    Music test();
}
           
System.out.println("****构造函数引入***");
        FunctionInterfaceTest functionInterfaceTest = Music::new;
        System.out.println(functionInterfaceTest.test());
           

 运行结果:

JDK8新特性简介、Lambda表达式、Stream流常用api介绍JDK8新特性简介、Lambda表达式、Stream流常用api介绍

Lambda(简化匿名内部类)

使用Lambda表达式排序

List<Music> musicList = new ArrayList<>();
        musicList.add(new Music("《好好》","阿信",20));
        musicList.add(new Music("《晴天》","周杰伦",21));
        musicList.add(new Music("《云烟成雨》","房东的猫",18));
        musicList.sort((music1,music2)->music1.getAge()-music2.getAge());
        musicList.forEach(o->System.out.println(o.toString()));
           

运行结果

JDK8新特性简介、Lambda表达式、Stream流常用api介绍JDK8新特性简介、Lambda表达式、Stream流常用api介绍

Steam流

List<Music> musicList = new ArrayList<>();
        musicList.add(new Music("《好好》","阿信",20));
        musicList.add(new Music("《晴天》","周杰伦",21));
        musicList.add(new Music("《云烟成雨》","房东的猫",18));
        musicList.add(new Music("《云烟成雨》","房东的猫",20));
           

limit分页

/** limit分页 */
        System.out.println("limit分页");
        musicList.stream().skip(1).limit(3).forEach(music-> System.out.println(music));
           

运行结果

JDK8新特性简介、Lambda表达式、Stream流常用api介绍JDK8新特性简介、Lambda表达式、Stream流常用api介绍

注意:skip为跳过元素

sorted 排序

/** sorted 排序 */
        System.out.println("sorted 排序");
        System.out.println("降序");
        musicList.stream().sorted((music1,music2)->music2.getAge()-music1.getAge()).forEach(music -> System.out.println(music));
        System.out.println("升序");
        musicList.stream().sorted(Comparator.comparingInt(Music::getAge)).forEach(music -> System.out.println(music));
           

运行结果:

JDK8新特性简介、Lambda表达式、Stream流常用api介绍JDK8新特性简介、Lambda表达式、Stream流常用api介绍

filter过滤

/** filter过滤*/
        System.out.println("filter过滤");
        musicList.stream().filter(music -> "《云烟成雨》".equals(music.getName()) && music.getAge() > 18)
                .forEach(v -> System.out.println(v));
           

Match匹配

/** match 匹配 **/
        System.out.println("anyMatch匹配");
        /** 若任意元素满足条件即可*/
        boolean a = musicList.stream().anyMatch(music -> "《好好》".equals(music.getName()));
        System.out.println(a);
        /** 若所有元素满足条件*/
        boolean b = musicList.stream().allMatch(music -> "《好好》".equals(music.getName()));
        System.out.println(b);
        /** 所有元素都不满足条件*/
        boolean c = musicList.stream().noneMatch(music -> "《好好》".equals(music.getName()));
        System.out.println(c);
           

List中元素属性查找最大值和最小值

/** 使用stream流 查找list中的属性 最大值和最小值**/
//        Optional<Music> max = musicList.stream().max((music1, music2) -> music1.getAge() - music2.getAge());
//        System.out.println("最大值:"+max);
        Optional<Music> max = musicList.stream().max(Comparator.comparingInt(Music::getAge));
        System.out.println("最大值:"+max);
           

运行结果:

JDK8新特性简介、Lambda表达式、Stream流常用api介绍JDK8新特性简介、Lambda表达式、Stream流常用api介绍

List中元素属性求和

Optional<Music> musicOptional = musicList.stream().reduce((music, music2) ->
                new Music("sumAge", "ls", music.getAge() + music2.getAge())
        );
        System.out.println(musicOptional.get());
           

运行结果

JDK8新特性简介、Lambda表达式、Stream流常用api介绍JDK8新特性简介、Lambda表达式、Stream流常用api介绍

List转Set

Set<Music> musicSet = musicList.stream().collect(Collectors.toSet());
        musicSet.forEach(music -> {
            System.out.println(music.toString());
        });
               
           

运行结果

JDK8新特性简介、Lambda表达式、Stream流常用api介绍JDK8新特性简介、Lambda表达式、Stream流常用api介绍

注意:这里Music类使用了@Data注解重写了equals方法。若转换成set集合后没有对元素去重,对象应该没有重写equals方法。

List转Map集合

Map<String, Music> musicMap = musicList.stream().collect(Collectors.toMap(Music::getName, Function.identity(),(music1,music2) -> music2));
        musicMap.forEach((k,v)-> System.out.println(k+"------"+v.toString()));
           

运行结果

JDK8新特性简介、Lambda表达式、Stream流常用api介绍JDK8新特性简介、Lambda表达式、Stream流常用api介绍

注:Function.identity等价于 t->t。也可写成Map<String, Music> musicMap = musicList.stream().collect(Collectors.toMap(Music::getName, music -> music)),但是若该musicList集合中key有相同的值,则会抛异常java.lang.IllegalStateException: Duplicate key Music(name=《云烟成雨》, author=房东的猫, age=18),请不要使用该方式,应该指明若存在相同key的情况下是否替换旧值。

Java 8允许在接口中加入具体方法。接口中的具体方法有两种,default方法和static方法,identity()就是Function接口的一个静态方法。

Function.identity()返回一个输出跟输入一样的Lambda表达式对象,等价于形如

t -> t

形式的Lambda表达式。

List转Map并指定分组属性

代码

public class StreamDemo {

    public static void main(String[] args) {
        List<Music> list = new ArrayList<>();
        list.add(new Music("好好", "五月天"));
        list.add(new Music("理想", "赵雷"));
        list.add(new Music("突然好想你", "五月天"));
        Map<String, List<Music>> map = list.stream().collect(Collectors.groupingBy(Music::getAuthor));
        map.forEach((k, v) -> {
            System.out.println(k + ":" + v.toString());
        });
    }
}
           

运行结果

JDK8新特性简介、Lambda表达式、Stream流常用api介绍JDK8新特性简介、Lambda表达式、Stream流常用api介绍

List去重

代码(若作者相同,则删除后面的对象)

List<Music> arrayList = list.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(Music::getAuthor))), ArrayList::new));
arrayList.forEach(System.out::println);
           

运行结果

JDK8新特性简介、Lambda表达式、Stream流常用api介绍JDK8新特性简介、Lambda表达式、Stream流常用api介绍

Optional

public class OptionalTest {
    public static void main(String[] args) {
        Music music = new Music();
        music.setName("五月天");
        String name = music.getName();
        Optional<String> nameOptional = Optional.ofNullable(name);
        /** 判断是否为空 isPresent() 如果是false,则对象为null;如果为true,对象不为null */
//        boolean present = nameOptional.isPresent();
//        System.out.println(nameOptional.get());
//        System.out.println(present);

        /** 如果为null,设置默认值 */
//        String newName = Optional.ofNullable(name).orElse("含老八");
//        System.out.println(newName);

        /** filter过滤 */
        boolean present = Optional.ofNullable(name).filter(s -> "五月天".equals(name)).isPresent();
        System.out.println(present);

        /** 直接判断是否有值 */
        Optional.ofNullable(name).ifPresent(System.out::println);
    }
}