干货有质量,水文有情怀,微信搜索【程序控】,关注这个有趣的灵魂
【本篇是集合中的Set篇,以下涉及源码基于JDK1.8】
这一篇Set篇可以说是基于Map篇的,HashSet底层是HashMap,数组+链表+红黑树。TreeSet底层是TreeMap,是基于红黑树(是一个自平衡的二叉树),LinkedHashSet底层数据结构由哈希表(是一个元素为链表的数组)和双向链表组成。
本篇是Java基础中最重要的知识点集合Map篇。Java集合是java提供的工具包,包含了常用的数据结构:集合、链表、队列、栈、数组、映射等。Java集合工具包位置是java.util.*,Java集合主要可以划分为4个部分:List列表、Set集合、Map映射、工具类(Iterator迭代器、Enumeration枚举类、Arrays和Collections)。接下来我们一起学习吧,博主水平有限,哪里有不对的地方欢迎大佬指出斧正。
Colletcion和Map结构如下图所示:
大致介绍一下:Collection和Map是两个高度抽象的接口;
Collection抽象的是集合,包含了集合的基本操作和属性,Collection主要包含List和Set两大分支。List是有序的链表,允许存储重复的元素,List的主要实现类有LinkedList, ArrayList, Vector, Stack。Set是不允许存在重复元素的集合,Set的主要实现类有HastSet和TreeSet(依赖哈希实现,后面介绍)。
Map是一个映射接口,即存储Key-Value键值对的集合(和redis存储类似),AbstractMap是个抽象类,它实现了Map接口中的大部分API,而常见的HashMap,TreeMap都是继承于AbstractMap。HashTable继承于Dictionary,但也实现了Map接口。
集合是Java中用来存储多个对象的一个容器,我们知道容器数组,数组长度不可变,且只能存储同样类型的元素,数组可以存储基本类型或者引用类型;而集合长度可变,可以存储不同类型元素(但是我们一般不这么干),集合只能存储引用类型(存储的基本类型会变成包装类);
集合的Fail-Fast机制?
fail-fast 机制是java集合(Collection)中的一种错误机制。当多个线程对同一个集合的内容进行操作时,就可能会产生 fail-fast 事件。例如:当某一个线程A通过 iterator 去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException 异常,产生 fail-fast 事件;当然,不仅是多个线程,单个线程也会出现 fail-fast 机制,比如单线程下的iterator迭代器遍历时调用集合的增删改等操作会抛出java.util.ConcurrentModificationException,从而产生fail-fast机制。
Set接口
HashSet集合
首先,我们也来看看HashSet的类继承结构图:
HashSet定义:
public class HashSet
extends AbstractSet
implements Set, Cloneable, java.io.Serializable {}
复制代码
HashSet简介:
HashSet实现Set接口,不保证迭代顺序,允许元素为null。
HashSet底层实际上是一个非同步的HashMap实例,初始容量非常影响迭代性能。
HashSet除了在元素的存储上是无序的以外,还是不能够存储重复的元素。不能重复元素是根据元素继承的两个方法来判断,hashCode和equals,当存储元素时,首先判断要存入的元素和已存在的元素的哈希值是否相同,若不相同存入,若相同则利用equals判断两个元素是否相同,若不相同,则存入,若相同则放弃。而hashCode和equlas是在存入元素自动调用的。
HashSet实际上就是封装了HashMap,操作HashSet元素实际上就是操作HashMap。这也是面向对象的一种体现,重用性贼高!
我们来看下源码:
HashSet内部实际上是一个HashMap,内部的很多操作也是通过HashMap来实现的,这里不再多说。
TreeSet集合
首先,我们也来看看TreeSet的类继承结构图:
TreeSet定义:
public class TreeSet extends AbstractSet
implements NavigableSet, Cloneable, java.io.Serializable {}
复制代码
TreeSet简介:
TreeSet实现NavigableSet接口,可以实现排序功能,底层实际上是非同步的TreeMap实例,即红黑树存储。
TreeSet中存储的类型必须是一致的,不能一下存int,一下又存string。
看下源码,恍然大悟~~
LinkedHashSet集合
首先,我们也来看看LinkedHashSet的类继承结构图:
LinkedHashSet定义:
public class LinkedHashSet
extends HashSet
implements Set, Cloneable, java.io.Serializable { }
复制代码
LinkedHashSet简介:
LinkedHashSet底层实际上是一个HashMap+双向链表实例(其实就是LinkedHashMap)。
LinkedHashSet迭代有序,允许null,性能比HashSet差一丢丢,因为要维护一个双向链表。
初始容量与迭代无关,LinkedHashSet迭代的是双向链表。
总结:可以很明显地看到,Set集合的底层就是Map,由于在Map篇已经详细分析,这里就不多分析了~~
作者寄语
本文介绍了Java集合中的Set知识,后面还有更多文章,欢迎大家阅读,本人见识有限,写的博客难免有错误或者疏忽的地方,还望各位大佬指点,感激不尽。
你知道的越多,你不知道的也越多。keep hungry keep foolish!