java8新特性

简介: java8新特性

Lambda表达式

Lambda 表达式的基础语法:Java8中引入了一个新的操作符 “->” 该操作符称为箭头操作符或 Lambda 操作符, 箭头操作符将 Lambda 表达式拆分成两部分:

  • 左侧:Lambda 表达式的参数列表,参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型
  • 右侧:Lambda 表达式中所需执行的功能, 即 Lambda 体

格式一:无参数,无返回值

匿名类部类的方式实现接口

  @Test
  public void test1(){
    int num = 0;//jdk 1.7 前,必须是 final,1.7以后可以不写但还是final类型
    Runnable r = new Runnable() {
      @Override
      public void run() {
        System.out.println("Hello World!" + num);
      }
    };
    Thread t = new Thread(r);
    t.start();
    System.out.println("-------------------------------");
    Runnable r1 = () -> System.out.println("Hello Lambda!");
    Thread t1 = new Thread(r1);
    t1.start();
  }

格式二:有一个参数,无返回值

()可以省略不写

  @Test
  public void test3(){
        Consumer<String> con1 = (x) -> System.out.println(x);
        con1.accept("bushro1");
        Consumer<String> con2 = x -> System.out.println(x);
        con2.accept("bushro2");
   }

格式三:两个以上参数,有返回值

()不能省略

  @Test
  public void test3(){
    //Lambda 体中只有一条语句
    Comparator<Integer> com1 = (x, y) ->Integer.compare(x, y);
    //Lambda 体中有多条语句
    Comparator<Integer> com2 = (x, y) -> {
      System.out.println("函数式接口");
      return Integer.compare(x, y);
    };
  }

排序使用

      List<Employee> emps = Arrays.asList(
      new Employee(101, "张三", 18, 9999.99),
      new Employee(102, "李四", 59, 6666.66),
      new Employee(103, "王五", 28, 3333.33),
      new Employee(104, "赵六", 8, 7777.77),
      new Employee(105, "田七", 38, 5555.55)
  );
  @Test
  public void test3(){
        Collections.sort(emps, (e1, e2) -> {
            if(e1.getAge() == e2.getAge()){
                return e1.getName().compareTo(e2.getName());
            }else{
                return Integer.compare(e1.getAge(), e2.getAge());
            }
        });
        //使用lambda表达式排序
        Collections.sort(emps, (e1, e2) -> {
            return Integer.compare(e1.getAge(), e2.getAge());
        });
        emps.sort(new Comparator<Employee>() {
            @Override
            public int compare(Employee o1, Employee o2) {
                return Integer.compare(o1.getAge(), o2.getAge());
            }
        });
        //使用lambda表达式排序
        emps.sort((e1,e2)->{
            return -Integer.compare(e1.getAge(), e2.getAge());
        });
    }

Lambda 表达式“函数式接口”的支持

函数式接口:接口中只有一个抽象方法的接口,称为函数式接口。 可以使用注解 @FunctionalInterface 修饰:可以检查是否是函数式接口

如:对一个数进行运算操作

接口

@FunctionalInterface
public interface MyFun {
  public Integer getValue(Integer num);
}

这样我们就不需要为每种运行都写一个方法了。

  @Test
  public void test4(){
    Integer num = operation(100, (x) -> x * x);
    System.out.println(num);
    System.out.println(operation(200, (y) -> y + 200));
  }
  public Integer operation(Integer num, MyFun mf){
    return mf.getValue(num);
  }

四大内置核心函数式接口

20210419204142531.png

Consumer : 消费型接口

  //Consumer<T> 消费型接口 :
  @Test
  public void test1(){
    happy(10000, (m) -> System.out.println("消费:" + m + "元"));
  } 
  public void happy(double money, Consumer<Double> con){
    con.accept(money);
  }

Supplier : 供给型接口

需求:产生指定个数的整数,并放入集合中

    public static List<Integer> getNumList(int num, Supplier<Integer> sup){
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < num; i++) {
            Integer n = sup.get();
            list.add(n);
        }
        return list;
    }
    //调用
    List<Integer> numList = getNumList(10, () -> (int)(Math.random() * 100));
    for (Integer num : numList) {
           System.out.println(num);
    }

Function<T, R> : 函数型接口

例如:处理字符串

  public String strHandler(String str, Function<String, String> fun){
    return fun.apply(str);
  }
    //去除头尾空格
    String newStr = strHandler("  aaa ", (str) -> str.trim());
    System.out.println(newStr);
    //截取2-5
    String subStr = strHandler("abcdefg", (str) -> str.substring(2, 5));
    System.out.println(subStr);

Predicate : 断言型接口

将满足条件的字符串,放入集合中

  public List<String> filterStr(List<String> list, Predicate<String> pre){
    List<String> strList = new ArrayList<>();
    for (String str : list) {
      if(pre.test(str)){
        strList.add(str);
      }
    }
    return strList;
  }
  //找出长度大于3的字符串
  List<String> list = Arrays.asList("aaaaaaa", "bbbbbbbb", "cc", "www", "ok");
  List<String> strList = filterStr(list, (s) -> s.length() > 3);
  for (String str : strList) {
      System.out.println(str);
  }

Stream Api

Stream是数据渠道,用于操作数据源(集合,数组等)所生成得元素序列。而集合讲得是数据,流讲得是计算。

在Stream操作过程中,可以对数据流做过滤,排序,切片等操作,但是操作之后会产生一个新的流,而数据源则不会发生改变。

  • Stream 自己不会存储元素。
  • Stream 不会改变源对象。相反,它会返回一个持有结果得新Stream
  • Stream 操作时延迟执行得,这意味着它们会等到需要结果时才执行。(延迟加载)

三个步骤:创建stream->中间操作->终止操作

流进行了终止操作后,不能再次使用

创建Stream流

  @Test
  public void test1(){
    //通过Collection系列集合提供的stream()或者parallelStream()
    List<String> list=new ArrayList<>();
    Stream<String> stream1 = list.stream();
    //通过Arrays中的静态方法stream()获取数组流
    String em[]=new String[]{"aa","bb"};
    Stream<String> stream2 = Arrays.stream(em);
    //通过Stream类中的静态方法of
    Stream<String> stream3 = Stream.of("aa", "bb");
  }

筛选与切片

  • filter——接收 Lambda , 从流中排除某些元素。
  • limit——截断流,使其元素不超过给定数量。
  • skip(n) —— 跳过元素,返回一个扔掉了前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。与 limit(n) 互补
  • distinct——筛选,通过流所生成元素的 hashCode() 和 equals() 去除重复元素
  //内部迭代:迭代操作 Stream API 内部完成
  @Test
  public void test2(){
    //所有的中间操作不会做任何的处理
    Stream<Employee> stream = emps.stream()
      .filter((e) -> {
        return e.getAge() <= 35;
      });
    //只有当做终止操作时,所有的中间操作会一次性的全部执行,称为“惰性求值”
    stream.forEach(System.out::println);
  }

映射

  • map——接收 Lambda , 将元素转换成其他形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素。
  • flatMap——接收一个函数作为参数,将流中的每个值都换成另一个流,然后把所有流连接成一个流
    List<String> strList = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
    Stream<String> stream = strList.stream()
         .map(String::toUpperCase);
    stream.forEach(System.out::println);
    /**
     * <h2>查找所有可用的优惠券模板</h2>
     * @return {@link CouponTemplateSDK}s
     */
    @Override
    public List<CouponTemplateSDK> findAllUsableTemplate() {
        List<CouponTemplate> templates =
                templateDao.findAllByAvailableAndExpired(
                        true, false);
        templates.stream().map(CouponTemplate::getExpired)
        return templates.stream()
                .map(this::template2TemplateSDK).collect(Collectors.toList());
    }
    /**
     * <h2>获取模板 ids 到 CouponTemplateSDK 的映射</h2>
     * @param ids 模板 ids
     * @return Map<key: 模板 id, value: CouponTemplateSDK>
     */
    @Override
    public Map<Integer, CouponTemplateSDK> findIds2TemplateSDK(
            Collection<Integer> ids) {
        List<CouponTemplate> templates = templateDao.findAllById(ids);
        return templates.stream().map(this::template2TemplateSDK)
                .collect(Collectors.toMap(
                        CouponTemplateSDK::getId, Function.identity()
                ));
    }
    /**
     * <h2>将 CouponTemplate 转换为 CouponTemplateSDK</h2>
     * */
    private CouponTemplateSDK template2TemplateSDK(CouponTemplate template) {
        return new CouponTemplateSDK(
                template.getId(),
                template.getName(),
                template.getLogo(),
                template.getDesc(),
                template.getCategory().getCode(),
                template.getProductLine().getCode(),
                template.getKey(),  // 并不是拼装好的 Template Key
                template.getTarget().getCode(),
                template.getRule()
        );
    }

排序

  • sorted()——自然排序
  • sorted(Comparator com)——定制排序
        List<String> strList = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
        strList.stream()
                .sorted()
                .forEach(System.out::println);
        System.out.println("------------------------------------");
        strList.stream()
                .sorted((x, y) -> {
                    return -x.compareTo(y);
                }).forEach(System.out::println);

查找与匹配

  • allMatch——检查是否匹配所有元素
  • anyMatch——检查是否至少匹配一个元素
  • noneMatch——检查是否没有匹配的元素
  • findFirst——返回第一个元素
  • findAny——返回当前流中的任意元素
  • count——返回流中元素的总个数
  • max——返回流中最大值
  • min——返回流中最小值

Status为Employee中的枚举类

        //所有集合中的Status是否为BUSY
      boolean bl = emps.stream()
        .allMatch((e) -> e.getStatus().equals(Status.BUSY));
     //获取最大值
      Integer ger[]=new Integer[]{2,4};
        Optional<Integer> max = Arrays.stream(ger).max((o1, o2) -> Integer.compare(o1, o2));
        System.out.println(max.get());
        //查找集合中大于1的个数
        List<Integer> list=new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(9);
        long count = list.stream().filter(e -> e > 1).count();
        System.out.println(count);

归约

  • reduce(T identity, BinaryOperator) / reduce(BinaryOperator) ——可以将流中元素反复结合起来,得到一个值。
        //从第0个开始反复计算
        List<Integer> integerList = Arrays.asList(1,2,3);
        Integer sum = integerList.stream()
                .reduce(0, (x, y) -> x + y);
        System.out.println(sum);
        /**
         * map+reduce
         * map取出数据,reduce进行累计
         */
        Optional<Integer> reduce = emps.stream()
                .map(e -> e.getAge())
                .reduce(Integer::sum);
        System.out.println(reduce.get());

收集

这个一个比较实用的方法

collect——将流转换为其他形式。接收一个 Collector接口的实现,用于给Stream中元素做汇总的方法。

        /**
         * map+collect
         * 取出数据后转成对应的类型
         */
        List<String> list1 = emps.stream()
                .map(Employee::getName)
                .collect(Collectors.toList());
        list1.forEach(System.out::println);
        //放入map中
        Map<Integer, String> collect = emps.stream()
                .collect(Collectors.toMap(e -> e.getId(), e -> e.getName()));
        System.out.println(collect.get(105));
        //其它类型的
        HashSet<String> collect1 = emps.stream()
                .map(e -> e.getName())
                .collect(Collectors.toCollection(HashSet::new));

集合最值操作

        //最大工资
        Optional<Double> max = emps.stream()
                .map(Employee::getSalary)
                .collect(Collectors.maxBy(Double::compare));
        System.out.println(max.get());
        //工资最小值对象
        Optional<Employee> op = emps.stream()
                .collect(Collectors.minBy((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary())));
        System.out.println(op.get());
        //求和
        Double sum = emps.stream()
                .collect(Collectors.summingDouble(Employee::getSalary));
        System.out.println(sum);
        //求平均值
        Double avg = emps.stream()
                .collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println(avg);
        //集合中的数量
        Long count = emps.stream()
                .collect(Collectors.counting());
        System.out.println(count);

分组:

public class Main {
    static List<Employee> emps = Arrays.asList(
            new Employee(102, "李四", 79, 6666.66, Employee.Status.BUSY),
            new Employee(101, "张三", 18, 9999.99, Employee.Status.FREE),
            new Employee(103, "王五", 28, 3333.33, Employee.Status.VOCATION),
            new Employee(104, "赵六", 8, 7777.77, Employee.Status.BUSY),
            new Employee(104, "赵六", 8, 7777.77, Employee.Status.FREE),
            new Employee(104, "赵六", 8, 7777.77, Employee.Status.FREE),
            new Employee(105, "田七", 38, 5555.55, Employee.Status.BUSY)
    );
    public static void main(String[] args) {
        Map<Employee.Status, List<Employee>> map = emps.stream()
                .collect(Collectors.groupingBy(Employee::getStatus));
        System.out.println(map);
        Map<Employee.Status, Map<String, List<Employee>>> map1 = emps.stream()
                .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
                    if(e.getAge() >= 60)
                        return "老年";
                    else if(e.getAge() >= 35)
                        return "中年";
                    else
                        return "成年";
                })));
       System.out.println(map1);
 }
相关文章
|
2月前
|
存储 安全 Java
Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
【10月更文挑战第17天】Java Map新玩法:探索HashMap和TreeMap的高级特性,让你的代码更强大!
78 2
|
2月前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
48 3
|
2月前
|
存储 Java 数据处理
Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位
【10月更文挑战第16天】Java Set接口凭借其独特的“不重复”特性,在集合框架中占据重要地位。本文通过快速去重和高效查找两个案例,展示了Set如何简化数据处理流程,提升代码效率。使用HashSet可轻松实现数据去重,而contains方法则提供了快速查找的功能,彰显了Set在处理大量数据时的优势。
37 2
|
2月前
|
存储 算法 Java
Java Set因其“无重复”特性在集合框架中独树一帜
【10月更文挑战第14天】Java Set因其“无重复”特性在集合框架中独树一帜。本文深入解析Set接口及其主要实现类(如HashSet、TreeSet)如何通过特定的数据结构(哈希表、红黑树)确保元素唯一性,并提供最佳实践建议,包括选择合适的Set实现类和正确实现自定义对象的`hashCode()`与`equals()`方法。
36 3
|
2月前
|
安全 Java API
Java 17新特性让你的代码起飞!
【10月更文挑战第4天】自Java 8发布以来,Java语言经历了多次重大更新,每一次都引入了令人兴奋的新特性,极大地提升了开发效率和代码质量。本文将带你从Java 8一路走到Java 17,探索那些能让你的代码起飞的关键特性。
93 1
|
2月前
|
编解码 Oracle Java
java9到java17的新特性学习--github新项目
本文宣布了一个名为"JavaLearnNote"的新GitHub项目,该项目旨在帮助Java开发者深入理解和掌握从Java 9到Java 17的每个版本的关键新特性,并通过实战演示、社区支持和持续更新来促进学习。
90 3
|
13天前
|
存储 Java 开发者
什么是java的Compact Strings特性,什么情况下使用
Java 9引入了紧凑字符串特性,优化了字符串的内存使用。它通过将字符串从UTF-16字符数组改为字节数组存储,根据内容选择更节省内存的编码方式,通常能节省10%至15%的内存。
|
22天前
|
存储 Java 数据挖掘
Java 8 新特性之 Stream API:函数式编程风格的数据处理范式
Java 8 引入的 Stream API 提供了一种新的数据处理方式,支持函数式编程风格,能够高效、简洁地处理集合数据,实现过滤、映射、聚合等操作。
39 6
|
1月前
|
分布式计算 Java API
Java 8引入了流处理和函数式编程两大新特性
Java 8引入了流处理和函数式编程两大新特性。流处理提供了一种声明式的数据处理方式,使代码更简洁易读;函数式编程通过Lambda表达式和函数式接口,简化了代码书写,提高了灵活性。此外,Java 8还引入了Optional类、新的日期时间API等,进一步增强了编程能力。这些新特性使开发者能够编写更高效、更清晰的代码。
33 4
|
2月前
|
存储 Java API
优雅地使用Java Map,通过掌握其高级特性和技巧,让代码更简洁。
【10月更文挑战第19天】本文介绍了如何优雅地使用Java Map,通过掌握其高级特性和技巧,让代码更简洁。内容包括Map的初始化、使用Stream API处理Map、利用merge方法、使用ComputeIfAbsent和ComputeIfPresent,以及Map的默认方法。这些技巧不仅提高了代码的可读性和维护性,还提升了开发效率。
97 3