集合的底层实现

集合的实现类:《ArrayList》,《LinkedList》,《HashMap》,《HashSet》,《LinkedHashMap》,《LinkedHashSet》,《Hashtable》,《ConcurrentHashMap》
各实现类的底层实现
1》ArrayList
A》ArrayList是list接口的可变数组的非同步实现,允许包含null在内的所有元素。
B》底层使用数组实现。
C》原本数组是定长的,基础数组的长度默认为16,加素因子默认为0.75,可储存长度为16*0.75=12。但是该集合为可变长数组,数组在扩容时,会将老数组拷贝一份到新的数组中,所以就完成了动态添加且不定长度的原因,但是每次数组容量增长,大约是之前容量的1.5倍,这种操作代价很高。
D》ArrayList中的remove方法会让下标到数组末尾的元素向前移动一个单位,并把最后一位的值置空,方便GC。
2》LinkedList
A》LinkedList是list的双向链表非同步实现,允许包括null在内的所有元素。
B》底层的数据结构基于双向链表,该数据结构被称为节点。
C》双线链表对应的类Node的实例,Node中包含的成员变量:prev、next、item。其中prev表示该节点的上一个节点,next表示该节点的下一个节点,item表示该节点的值。
D》它是分两半查找的。先判断index所在的链表,再去对应的链表查找,这样只要遍历一般就能完成。
E》链表本身可以自动增长的,所以是利用链表的特性直接完成动态长度的。
3》HashMap
A》HashMap是基于哈希表中Map接口的非同步实现的,允许使用null值和null键,但不保证映射的顺序
B》底层使用数组实现,数组中的每一项是单向链表,即数组和链表的结合体,当链表的长度大于一定阀值时,链表转化为红黑树,减少链表查询的时间。
C》HashMap在底层将key-value当成一个整体(Node对象)进行处理。HashMap底层采用一个Node[]数组来保存所有的key-value对,当需要存储一个Node对象时,会根据key的hash算法来决定其在数组中的存储位置,在根据equals方法决定其在该数组位置上的链表中的存储位置;当需要取出一个Node时,也会根据key的hash算法找到其在数组中的存储位置,再根据equals方法从该位置上的链表中取出该Node。
D》HashMap进行数组扩容需要重新计算扩容后每个元素在数组中的位置,很耗性能。
4》HashSet
HashSet基于HashMap实现,API也是对HashMap的行为进行了封装

Java 中的 Set 集合是一种不允许重复元素的集合接口,其底层实现依赖于 Map 集合。具体而言,Set 接口的实现类(如 HashSet、TreeSet 和 LinkedHashSet)通过内部使用对应的 Map 实现类(如 HashMap、TreeMap 和 LinkedHashMap)来存储元素[^1]。 ### HashSet 的底层实现 HashSet 是基于 HashMap 实现的。当向 HashSet 中添加元素时,实际上是将该元素作为 HashMap 的键(Key),而值(Value)则是一个固定的 Object 对象(通常是一个静态的 Object 实例)。这样做的目的是利用 HashMap 的键唯一性来保证 HashSet 中元素的唯一性。在遍历 HashSet 时,实际上是在遍历 HashMap 中的键集合[^5]。 ```java // HashSet 内部使用 HashMap 的示例 public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable { private transient HashMap<E, Object> map; // 构造方法中初始化 HashMap public HashSet() { map = new HashMap<>(); } // 添加元素时调用 HashMap 的 put 方法 public boolean add(E e) { return map.put(e, PRESENT) == null; } } ``` ### TreeSet 的底层实现 TreeSet 是基于 TreeMap 实现的。TreeSet 中的元素是有序的,默认情况下按照自然顺序排列(即元素必须实现 `Comparable` 接口),也可以通过提供自定义的 `Comparator` 来指定排序规则。TreeSet 通过 TreeMap 的键来存储元素,同样,值部分使用一个固定的 Object 对象[^4]。 ```java // TreeSet 内部使用 TreeMap 的示例 public class TreeSet<E> extends AbstractSet<E> implements NavigableSet<E>, Cloneable, java.io.Serializable { private transient NavigableMap<E, Object> m; // 构造方法中初始化 TreeMap public TreeSet() { this.m = new TreeMap<>(); } // 添加元素时调用 TreeMap 的 put 方法 public boolean add(E e) { return m.put(e, PRESENT) == null; } } ``` ### LinkedHashSet 的底层实现 LinkedHashSet 是基于 LinkedHashMap 实现的。与 HashSet 类似,LinkedHashSet 也使用 LinkedHashMap 的键来存储元素,值部分同样是一个固定的 Object 对象。不同之处在于,LinkedHashSet 保持了元素插入的顺序,这是通过 LinkedHashMap 维护的一个双向链表实现的[^2]。 ```java // LinkedHashSet 内部使用 LinkedHashMap 的示例 public class LinkedHashSet<E> extends HashSet<E> implements Set<E>, Cloneable, java.io.Serializable { // 构造方法中初始化 LinkedHashMap public LinkedHashSet() { super(new LinkedHashMap<>()); } } ``` ### Set 集合的核心特性 - **无重复元素**:由于底层使用了 Map 集合,而 Map 的键是唯一的,因此 Set 集合中的元素也具有唯一性。 - **无序性**:HashSet 不保证元素的顺序,其顺序可能会随着元素的增删而变化;而 LinkedHashSet 保持了元素的插入顺序;TreeSet 则按照自然顺序或自定义比较器进行排序。 - **高效去重**:Set 集合的核心特性之一是高效的去重功能,这得益于底层 Map 集合的键唯一性检查机制。 ### 总结 Set 集合实现依赖于 Map 集合,不同的 Set 实现类对应不同的 Map 实现类: - **HashSet** 使用 **HashMap** - **TreeSet** 使用 **TreeMap** - **LinkedHashSet** 使用 **LinkedHashMap** 通过这种方式,Set 集合能够利用 Map 的键唯一性来确保元素的唯一性,并且可以根据不同的需求选择合适的实现类来满足顺序和性能的要求[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值