JDK1.8新特性——Lambda详解| 8月更文挑战

661 阅读4分钟

前言

本篇主要讲述是Java中JDK1.8的一些新语法特性使用,主要是Lambda、Stream和LocalDate日期的一些使用讲解。

Lambda

  • Lambda 表达式,也可称为闭包,它是推动 Java 8 发布的最重要新特性。
  • Lambda 允许把函数作为一个方法的参数(函数作为参数传递进方法中)。
  • 使用 Lambda 表达式可以使代码变的更加简洁紧凑。 Lambda 表达式(lambda expression)是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。

1.Lambda表达式的结构

(parameters) -> expression 或 (parameters) ->{ statements; }

使用Lambda进行遍历:

System.out.println("map拉姆达表达式遍历:");
  map.forEach((k, v) -> {
   System.out.println("k=" + k + ",v=" + v);
 });

2.Stream

Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。

java.util.stream.Collectors,是从JDK1.8开始新引入的一个类。从源码的类注释上,我们可以知道:Collectors实现了各种有用归约的操作,例如类型归类到新集合、根据不同标准汇总元素等。透过示例,能让我们眼前一亮,短短的一行代码却能处理如此强大、复杂的功能:汇总、拼接、累加计算、分组等。

Collectors使用:

 *     Set<String> set = people.stream().map(Person::getName).collect(Collectors.toCollection(TreeSet::new));
 *
 *     // Convert elements to strings and concatenate them, separated by commas
 *     String joined = things.stream()
 *                           .map(Object::toString)
 *                           .collect(Collectors.joining(", "));

filter使用:

List<String> list = Arrays.asList("张三", "李四", "王五", "xuwujing");
String result3 = list.stream().filter(str -> "李四".equals(str)).findAny().orElse("找不到!");
String result4 = list.stream().filter(str -> "李二".equals(str)).findAny().orElse("找不到!");

//stream 过滤之后 2:李四
//stream 过滤之后 3:找不到!

limit使用:

Random rd = new Random();
 System.out.println("取到的前三条数据:");
 rd.ints().limit(3).forEach(System.out::println);

分组:groupingBy/groupingByConcurrent

按照条件对元素进行分组,和 SQL 中的 group by 用法有异曲同工之妙,通常也建议使用Java代码进行分组处理以减轻数据库SQL压力。

分组涉及以下方法:

  • Collectors.groupingBy(…):普通分组。
  • Collectors.groupingByConcurrent(…):线程安全的分组。

分组后,返回的是一个Map集合,其中key作为分组对象,value作为对应分组结果。

比如,考虑到People集合中可能会存在同龄人,将集合按照年龄进行分组:

Map<Integer, List<People>> groupingByAge = allPeoples.stream().collect(Collectors.groupingBy(People::getAge));

3.LocalDate

  • Instant:瞬时时间。
  • LocalDate:本地日期,不包含具体时间, 格式 yyyy-MM-dd。
  • LocalTime:本地时间,不包含日期. 格式 yyyy-MM-dd HH:mm:ss.SSS 。
  • LocalDateTime:组合了日期和时间,但不包含时差和时区信息。
  • ZonedDateTime:最完整的日期时间,包含时区和相对UTC或格林威治的时差。
//获取当前的时间,包括毫秒
  LocalDateTime ldt = LocalDateTime.now();
  System.out.println("当前年:"+ldt.getYear());   //2021
  System.out.println("当前年份天数:"+ldt.getDayOfYear());//172 
  System.out.println("当前月:"+ldt.getMonthValue());
  System.out.println("当前时:"+ldt.getHour());
  System.out.println("当前分:"+ldt.getMinute());
  System.out.println("当前时间:"+ldt.toString());
 //   当前年:2021
 //   当前年份天数:365
 //   当前月:8
 //   当前时:10
 //   当前分:24
 //   当前时间:2021-8-1T15:24:35.833

JVM新特性

JDK8在JVM中修改重要有:

  • 新增JVM工具:jdeps提供了用于分析类文件的命令行工具。
  • 使用metaSpace代替永久区
  • 新增NMT(Native Memeory Trace)本地内存跟踪器

HashMap变化

JDK8优化了HashMap的实现, 主要优化点包括:

  • 将链表方式修改成链表或者红黑树的形式
  • 修改resize的过程,解决JDK7在resize在并发场景下死锁的隐患
  • JDK1.7存储使用Entry数组, JDK8使用Node或者TreeNode数组存储

当链表长度大于8是链表的存储结构会被修改成红黑树的形式。

查询效率从O(N)提升到O(logN)。链表长度小于6时,红黑树的方式退化成链表。

JDK7链表插入是从链表头部插入, 在resize的时候会将原来的链表逆序。

JDK8插入从链表尾部插入, 因此在resize的时候仍然保持原来的顺序。