hashtable arraylist 容量

本文深入探讨了ArrayList的容量管理,解释了其自动增长机制及其对性能的影响,并提供了确保高效添加大量元素的方法,同时对比了与HashTable在容量调整上的区别。

  Each ArrayList instance has a capacity. The capacity is the size of the array used to store the elements in the list. It is always at least as large as the list size. As elements are added an ArrayList, its capacity grows automatically. The details of the growth policy are not specified beyond the fact that adding an element has constant amortized time cost.
   An application can increase the capacity of an ArrayList instance before adding a large number of elements using the ensureCapacity operation. This may reduce the amount of incremental reallocation.
    这里说到ArrayList的一个容量的问题,如果想要Add数量比较多的元素,最好要使用该类
的一个叫做ensureCapacity的方法来确保ArrayList实例具有你所要指定的一个最小的容量。这样的话,对于大容量ArrayList实例,应该就可以由JDK正确地指定到内存中了,这些内存段是否连续,当然是由JDK来处理的问题了。至于这个最小的容量可以达到多少,这里没有讲明,不过应该是和内存多少和每个元素的大小有关系的吧,不好一概而论!
    防止out of memory,有一个方法,就是根据每次调用add方法的时候add的返回值(boolean型)来判断!
至于hashTable,与容量有关的是一下的一段:
    The initial capacity controls a tradeoff between wasted space and the need for rehash operations, which are time-consuming. No rehash operations will ever occur if the initial capacity is greater than the maximum number of entries the Hashtable will contain divided by its load factor. However, setting the initial capacity too high can waste space.
    这里提到初始容量和rehash方法,也就是hashtable在初始容量不够用的情况下可以通过
rehash方法自动增加容量,至于可以增加多少,文档也没有提,显然也是类似于ArrayList的吧。

<think>我们正在讨论ArrayListHashtable的区别。注意,这两者是完全不同的数据结构,分别属于Java集合框架中的不同类别。 ArrayList实现了List接口,而Hashtable实现了Map接口。因此,它们的设计目的和使用场景有本质区别。 根据引用[1]和引用[3],我们可以总结如下: ArrayList: - 基于动态数组实现,提供快速随机访问(通过索引)。 - 在中间插入或删除元素效率较低,因为需要移动元素。 - 允许重复元素和null元素。 - 不是线程安全的(与Vector不同,Vector是线程安全的但性能较低)。 Hashtable: - 实现了Map接口,存储键值对(key-value pairs)。 - 键和值都不允许为null(引用[1]和[2])。 - 方法是同步的(线程安全),因此多线程环境下可以使用,但性能可能不如ConcurrentHashMap。 - 通过哈希表实现,提供快速的插入和查找(基于键)。 因此,主要区别可以总结如下: 1. 数据结构: - ArrayList:动态数组,顺序存储。 - Hashtable:哈希表,键值对存储。 2. 元素存储: - ArrayList:存储单个元素(可以重复)。 - Hashtable:存储键值对(键唯一,值可以重复)。 3. 空值: - ArrayList:允许空元素。 - Hashtable:键和值都不允许为空。 4. 线程安全: - ArrayList:非线程安全(需要外部同步)。 - Hashtable:线程安全(方法同步)。 5. 性能: - ArrayList:随机访问(get(index))高效,时间复杂度$O(1)$;但在中间插入或删除元素需要移动元素,时间复杂度$O(n)$。 - Hashtable:插入、删除和查找(基于键)平均时间复杂度为$O(1)$(取决于哈希函数和冲突情况)。 6. 遍历方式: - ArrayList:可以使用索引(for循环)、迭代器(Iterator)或增强for循环。 - Hashtable:可以使用枚举(Enumeration)或迭代器(通过entrySet、keySet或values)。 7. 扩容机制: - ArrayList:默认初始容量为10,增长时增加50%(即新容量为旧容量的1.5倍)。 - Hashtable:默认初始容量为11,增长方式为old*2+1(即新容量为旧容量的2倍加1)。 8. 使用场景: - ArrayList:需要频繁按索引访问元素,且元素数量变化不大,或者主要在末尾添加元素。 - Hashtable:需要存储键值对,并且要求线程安全,且不允许空键或空值。 注意:由于Hashtable是遗留类,现在通常推荐使用ConcurrentHashMap来实现线程安全的Map,或者使用HashMap(非线程安全)在单线程环境下使用。 下面我们以表格形式进行对比: | 特性 | ArrayList | Hashtable | |--------------|--------------------------------------------|------------------------------------------------| | 接口实现 | `List` | `Map` | | 数据结构 | 动态数组 | 哈希表 | | 存储方式 | 单个元素(有序,可重复) | 键值对(键唯一,值可重复) | | 空值 | 允许空元素 | 键和值都不允许为空 | | 线程安全 | 否 | 是(同步方法) | | 随机访问 | 高效($O(1)$) | 通过键访问高效(平均$O(1)$) | | 插入/删除 | 中间位置效率低($O(n)$) | 平均$O(1)$(取决于哈希冲突) | | 扩容机制 | 默认10,增长50%(即1.5倍) | 默认11,增长方式为old*2+1 | | 遍历方式 | 索引、迭代器、增强for | 枚举、迭代器(通过entrySet、keySet等) | | 使用场景 | 按索引访问为主,少量插入删除(尤其是尾部) | 需要线程安全的键值对存储,且不允许空键/空值 | 综上所述,ArrayListHashtable在数据结构、用途和特性上有显著差异。选择哪一个取决于具体需求:需要存储单个元素的有序集合还是键值对映射,以及是否需要线程安全等。 §§相关问题§§ 1. ArrayList和LinkedList在性能上有何区别? 2. Hashtable和HashMap在线程安全方面有何不同? 3. 在Java中,如何选择使用ArrayList还是LinkedList? 4. 为什么Hashtable不允许null键和null值? 5. 如何实现ArrayList的线程安全版本?</think>### ArrayListHashtable 的区别 ArrayListHashtableJava 集合框架中**完全不同的数据结构**,主要区别体现在以下方面: | 特性 | ArrayList | Hashtable | |--------------|----------------------------------------|----------------------------------------| | **接口实现** | 实现 `List` 接口 | 实现 `Map` 接口 | | **数据结构** | 动态数组 | 哈希表(数组+链表) | | **存储方式** | 有序的单元素集合(可重复) | 键值对(Key-Value)存储 | | **空值支持** | ✅ 允许 `null` 元素 | ❌ 键和值均不允许 `null`[^1][^2] | | **线程安全** | ❌ 非线程安全(需手动同步) | ✅ 线程安全(方法使用 `synchronized`) | | **扩容机制** | 默认扩容 50%(新容量=旧容量×1.5) | 扩容公式:新容量=旧容量×2 +1[^1] | | **访问效率** | 随机访问快($O(1)$) | 按键查找快(平均$O(1)$) | | **插入效率** | 尾部插入快($O(1)$),中间插入慢($O(n)$) | 插入快(平均$O(1)$) | | **遍历方式** | 索引、迭代器、增强 for 循环 | 枚举器(Enumeration)、迭代器 | #### 详细说明: 1. **数据结构差异** - **ArrayList**:基于动态数组,内存连续分配。适合随机访问,但中间插入/删除需移动元素[^3]。 - **Hashtable**:基于哈希桶(数组+链表),通过哈希函数计算键的位置。适合快速查找键值对[^1]。 2. **线程安全性** - ArrayList 是非线程安全的,多线程操作需使用 `Collections.synchronizedList()` 或 `CopyOnWriteArrayList`。 - Hashtable 所有方法都是同步的(`synchronized`),可直接用于多线程环境(但性能低于 `ConcurrentHashMap`)[^1][^2]。 3. **空值处理** ```java // ArrayList 允许 null List<String> list = new ArrayList<>(); list.add(null); // ✅ 允许 // Hashtable 禁止 null Hashtable<String, String> table = new Hashtable<>(); table.put("key", null); // ❌ 抛出 NullPointerException ``` 4. **性能场景** - 需要 **按索引快速访问** → 选择 ArrayList - 需要 **按键快速查找/更新** → 选择 Hashtable(或 HashMap) - 需要 **频繁在中间插入/删除** → 考虑 LinkedList(非 ArrayList) 5. **扩容开销** - ArrayList 扩容时复制整个数组,大集合扩容成本高[^3]。 - Hashtable 扩容需重新计算所有键的哈希位置(类似 HashMap)。 > 💡 **现代替代方案**: > - 单线程环境用 `HashMap` 替代 Hashtable(性能更高) > - 多线程环境用 `ConcurrentHashMap` 替代 Hashtable(锁粒度更细)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值