欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java8 新特性

程序员文章站 2022-05-22 19:22:30
...

1 数据结构的更新

1.1 HashMap 的数据结构更新

1.2 ConcurrentHashMap 的数据结构更新

2 hotspot JVM 内存结构更新

3 函数式接口

4 Lambda 表达式

5 Stream API

一、数据结构的更新

1.1 HashMap 的数据结构更新

在 jdk1.8前 HashMap 底层是用数组 + 链表来实现的,而在 jdk1.8 后 HashMap 采用数组 + 链表 + 红黑树进行实现。

下面先看看 jdk1.7 的数据结构:
Java8 新特性
(网上借用的图片:https://blog.csdn.net/striveb/article/details/84657326)
HashMap 的底层实际上是一个 Entry[] 数组,该数组存放着一个个 Entry 实体,该实体包括 key,value,hash(key对应的 hash 值),以及下一个 Entry(形成链表)
Java8 新特性
HashMap 采用链地址法(拉链法)解决 hash 碰撞,当链的长度越来越长时,HashMap 的查询时间复杂度会趋向于 O(n),因为每次查找时,先计算 key 的hash值,根据 hash 值找到对应的桶(即数组的位置),假如在第一个位置查找不到时,需要遍历这个桶中的链表,先比较 hash 值,hash值相等时,再用 equals 方法比较(因为 hash 算法的原因,hash 值相等的两个对象不一定是同一个对象,equals 方法相等的对象即一定为相同的一个对象,为什么要这样比较可以查看一下 hash 和 equals 方法的文章),这样查找的效率是比较低的。

为了加快查询效率,在 jdk1.8 中,当链表的长度大于 8 时,将会把该链表转换为红黑树(平衡的二叉搜索树),查询时间复杂度会变成 O(log2N)

因为 HashMap的改变,相应的 Set 集合的数据结构也会改变,因为 Set 的底层也是用 HashMap 进行实现的(key 为存放的值,value为同一个 Object 对象)。

1.2 ConcurrentHashMap 的数据结构更新

在 jdk1.8 前,ConcurrentHashMap 是采用分段锁进行实现的,底层是一个Segment 数组,Segment 数组里面存放着一个个 Segment,因为 Segment 继承了 ReentrantLock 类,所以该类可以当做一个锁,同时 Segment 是一个小的 Hash 表,即存放着一个个 HashEntry[] 数组,HashEntry[] 存放着 Entry 类。
Java8 新特性
(图片出处:https://blog.csdn.net/justloveyou_/article/details/72783008)
在jdk1.7中ConcurrentHashMap使用锁分段技术提高并发访问效率。首先将数据分成一段一段地存储,然后给每一段数据配一个锁,当一个线程占用锁访问其中一段数据时,其他段的数据也能被其他线程访问。
在 jdk 1.8 后ConcurrentHashMap 取消了分段锁机制,利用 CAS + Synchronized 来保证并发更新的安全,底层依然采用数组+链表+红黑树的存储结构,ConcurrentHashMap 是线程安全的,并且它锁的粒度变的更细,在 jdk1.7 中它锁的是一个 Segment(一个分段),在 1.8 中它只是锁住一个桶的对象,并发效率更高。

2 Hotspot JVM 内存结构更新

在 jdk1.8 前,Oracle的 HotSpot JVM 中的堆逻辑上分为 年轻代、老年代、永久代三部分,而 jdk1.8 时,HotSpot JVM 的永久代被使用物理内存的元空间取代。

3 函数式接口

在jdk1.8 时,可以用 @FunctionalInterface 注解标注一个接口,标识它为一个函数式接口。那什么是函数式接口?
函数式接口就是一个只能含有一个抽象方法的接口,若有多个抽象将会报错,同时在 jdk1.8 中,可以使用 default 关键字标注一个方法,该方法即可在接口中实现。
Java8 新特性
为了方便开发,Java 8 提供了四大内置的函数式接口,方便配置 Lambda 表达式进行使用。
Java8 新特性

4 Lambda 表达式

Lambda 表达式在Java 语言中引入了一个新的语法元素和操作符。这个操作符为 “->” , 该操作符被称为 Lambda 操作符或剪头操作符。它将 Lambda 分为两个部分:
左侧:指定了 Lambda 表达式需要的所有参数
右侧:指定了 Lambda 体,即 Lambda 表达式要执行的功能。

语法格式一:

无参数,无返回值

() -> System.out.println("Hello Lambda!");
语法格式二:

有一个参数,并且无返回值

(x) -> System.out.println(x)
语法格式三:

若只有一个参数,小括号可以省略不写

x -> System.out.println(x)
语法格式四:

有两个以上的参数,有返回值,并且 Lambda 体中有多条语句

		Comparator<Integer> com = (x, y) -> {
			System.out.println("函数式接口");
			return Integer.compare(x, y);
		};
语法格式五:

若 Lambda 体中只有一条语句, return 和 大括号都可以省略不写

Comparator<Integer> com = (x, y) -> Integer.compare(x, y);
语法格式六:

Lambda 表达式的参数列表的数据类型可以省略不写,因为JVM编译器通过上下文推断出,数据类型,即“类型推断”

(Integer x, Integer y) -> Integer.compare(x, y);

下面看到一个创建线程的例子:

	@Test
	public void test1(){
		int num = 0;//jdk 1.7 前,必须是 final
		//正常实现方式
		Runnable r = new Runnable() {
			@Override
			public void run() {
				System.out.println("Hello World!" + num);
			}
		};
		
		r.run();
		
		System.out.println("-------------------------------");
		//利用 Lambda表达式的实现方式
		Runnable r1 = () -> System.out.println("Hello Lambda!");
		r1.run();
	}

例子二:

	//普通实现方式
    @Test
    public void test8(){
        Comparator<Integer> com = new Comparator<Integer>() {
            @Override
            public int compare(Integer x, Integer y) {
                return Integer.compare(x, y);
            }
        } ;
    }
	
	//Lambda 表达式
	@Test
    public void test7(){
        Comparator<Integer> com = (x, y) -> {
            System.out.println("函数式接口");
            return Integer.compare(x, y);
        };
    }

Lambda 表达式依赖于接口,每个 Lambda 表达式都对应着一个函数式接口,Java 8为我们内置了四大函数式接口以及其子类,如:Consumer、Supplier、Function、Predicate。其子类有(这只是一部分):
Java8 新特性
暂时更新这么多…,java 8 还有很多新特性这里只有一部分,有兴趣的可以看看这个视频,有空再更新:
链接:https://pan.baidu.com/s/1gfjkxibxL4eog9JulmVvyA
提取码:3bhi
需要的可以看看,尚硅谷的,感觉讲的还可以。

相关标签: java 8新特性