list和set底层数据结构

List和Set都继承了Collection接口

list是Java中的一个接口,它位于java.util包中,是有序的集合,元素可以重复,每个元素都有自己的索引

list集合的实现类有ArrayList,LinkedList,Vector

    ArrayList底层数据结构是动态数组(具有动态扩容的能力,当元素数量超过当前数据容量时,ArrayList会自动增加其容量),特点是查询快(数组有索引标记元素位置,查询的时候直接返回索引标记的数据即可),增 删慢(数组增加或者删除需要复制和移动数组中的数据),线程不同步

    LinkedList底层数据结构是双向链表(每个节点都包含对前一个节点后一个节点的引用),特点是增删快(只需要修改节点的前后引用即可),查询慢(链表没有对数据进行位置标记,每次获取固定位置的数据需要循环遍历链表)

    Vector底层数据结构是数组,线程同步(同步开销较高),性能不如ArrayList

set是Java中的一个接口,它位于java.util包中,是无序的集合,元素不能重复

set的实现类有HashSet,TreeSet,LinkerHashSet    

    HashSet (实际上是HashMap)底层数据结构是哈希表(数组+链表+红黑树),根据hashCode和equals方法来确定元素唯一性(基于HashCode来计算元素的存储位置,当存入的元素HashCode相同时,会调用equals方法进行确认,如果为true,则代表已经存在相同的元素)。允许存在null,但只能有一个。不保证集合的迭代顺序。线程不同步

    LinkedHashSet底层是数据结构(哈希表+双向链表)双向链表用来存储顺序,继承了HashSet,但是保证集合的迭代顺序。线程不同步

TreeSet实现了SortedSet接口,底层数据结构是红黑二叉树,实际上是TreeMap,可以确保元素处于排序状态。支持两种排序方式 自然排序和定制排序。线程不同步,不能有重复数据,不能有null数据,存储的数据类型必须是一致的。

当向treeSet添加自定义对象时,有两种排序方式:自然排序和定制排序

自然排序需要自定义对象实现Comparable接口,并重写comparaTo方法,在此方法中指明自定义的类的属性排序。

定制排序需要实现Comparator接口

都需要重写hashCode()与equals()方法

HashSet的扩容机制

底层数据结构哈希表(数组+链表+红黑树)

  1. 添加一个元素时,先得到hash值,再将hash值转化为索引,放在数组中该索引的位置
  2. 找到数组中索引位置,查看该索引是否有元素
  3. 若没有元素,则直接添加。若有元素,则调用equals方法计较。如果相同则不添加,若不同则添加在链表的尾部
  4. Jdk8中当链表中的元素个数打到8个,同时数组中的个数超过64时,就会进化成红黑树(进一步提高查询效率)。若链表中的元素达到8个,而数组中的数据未到64,则按照数组容量*2进行扩容,直到扩容到64再树化
  5. 第一次添加时,系统会扩容到,阈值为加载因子(0.75)*16 = 12
  6. 当整个数组中的元素个数打到12个 时,在添加第13个元素时,会触发数组扩容,此时阈值变为32*0.75=24,以此类推直到数组容量达到64时再树化。
<think>好的,用户现在问的是ListSet底层结构区别。之前他们问过关于Java继承中访问修饰符的问题,现在转向集合框架,可能需要了解这两种常用集合的底层实现,以便在实际开发中选择合适的结构。 首先,我需要回忆Java中ListSet的基本概念。List是有序、可重复的集合,而Set是无序、不可重复的。用户可能已经知道这些,但想深入底层结构。所以,我需要详细解释它们不同的实现类及其数据结构。 接下来,应该分点讨论。List的常见实现有ArrayList、LinkedListVector。ArrayList基于动态数组,LinkedList基于双向链表,Vector也是数组但线程安全。需要说明它们的增删改查的时间复杂度,比如ArrayList的随机访问快,但插入删除慢;LinkedList相反。 然后是Set的实现,如HashSet、LinkedHashSetTreeSet。HashSet基于哈希表(HashMap),LinkedHashSet在哈希表基础上维护链表保持插入顺序,TreeSet基于红黑树实现有序。要强调HashSet的O(1)时间复杂度,TreeSet的O(log n)排序特性。 还需要比较它们的底层数据结构差异,比如List多用数组或链表,而Set用哈希表或树结构。同时,线程安全方面,Vector是旧的实现,现在推荐用CopyOnWriteArrayList,而Set的线程安全版本如ConcurrentSkipListSet。 用户可能的应用场景:比如需要快速访问用ArrayList,频繁插入删除用LinkedList;去重用HashSet,需要排序用TreeSet。同时,线程安全的需求也是考虑点。 要确保回答结构清晰,可能用分点方式,结合代码示例表格对比,帮助用户理解不同实现之间的区别。还要注意提到版本变化,比如Java 8后HashMap的红黑树优化,避免过时信息。 最后,总结两者根本区别:List维护元素顺序索引,允许重复;Set确保唯一性,部分实现维护顺序。这样的结构能帮助用户更好地记忆应用。</think>**ListSet底层结构对比(基于Java集合框架)** $$数据结构对比表$$ \begin{array}{|c|c|c|c|} \hline \text{类型} & \text{典型实现类} & \text{底层结构} & \text{时间复杂度} \\ \hline \text{List} & ArrayList & \text{动态数组} & O(1)\text{随机访问}, O(n)\text{插入删除} \\ & LinkedList & \text{双向链表} & O(n)\text{访问}, O(1)\text{头尾操作} \\ & Vector & \text{同步数组} & \text{类似ArrayList但线程安全} \\ \hline \text{Set} & HashSet & \text{哈希表(HashMap实例)} & O(1)\text{平均查找时间} \\ & LinkedHashSet & \text{哈希表+双向链表} & \text{保持插入顺序} \\ & TreeSet & \text{红黑树} & O(\log n)\text{有序操作} \\ \hline \end{array} $$ **一、List核心实现解析** 1. **ArrayList(动态数组)** - 初始容量10,扩容公式:$$newCapacity = oldCapacity + (oldCapacity >> 1)$$ - 随机访问效率最高(通过索引直接定位) - 示例内存布局: ```java // JDK17+ 后优化为紧凑型存储 class ArrayList<E> { transient Object[] elementData; // 实际存储数组 private int size; // 当前元素数量 } ``` 2. **LinkedList(双向链表)** - 节点结构: ```java class Node<E> { E item; Node<E> prev; Node<E> next; } ``` - 插入删除只需修改指针,但访问需要遍历 **二、Set核心实现解析** 1. **HashSet(哈希表)** - 实际使用HashMap存储元素(值存于Key) - 哈希冲突解决方案:链表→红黑树(JDK8+) - 当链表长度≥8且数组长度≥64时转换 2. **TreeSet(红黑树)** - 基于TreeMap实现,元素必须实现Comparable接口 - 树结构保证元素有序性(自然排序或Comparator) **三、关键差异对比** ```java // 结构验证示例 List<Integer> list = new ArrayList<>(); list.add(1); list.add(1); // 允许重复 System.out.println(list.get(0)); // 支持索引访问 Set<Integer> set = new HashSet<>(); set.add(1); set.add(1); // 自动去重 // set.get(0); // 编译错误,无索引访问 ``` **四、性能选择指南** 1. **高频查询场景**:优先ArrayList(随机访问O(1)) 2. **频繁增删场景**:考虑LinkedList(头尾操作O(1)) 3. **去重需求**:HashSet(最快去重O(1)) 4. **排序需求**:TreeSet(自动排序O(log n)) **五、线程安全扩展** - List线程安全方案: ```java List<String> syncList = Collections.synchronizedList(new ArrayList<>()); // 或使用CopyOnWriteArrayList(写时复制) ``` - Set线程安全方案: ```java Set<String> syncSet = Collections.synchronizedSet(new HashSet<>()); // 或使用ConcurrentSkipListSet(跳表实现) ``` **底层结构演进**:JDK8后HashMap的链表长度超过阈值时会转换为红黑树,这使得HashSet在最坏情况下的查找性能从O(n)提升到O(log n),这是List结构所不具备的优化特性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值