Java常用集合使用
来源:互联网 发布:软件开发甲级资质 编辑:程序博客网 时间:2024/06/06 04:14
常用的集合类型有Set系列、Map系列、List系列,下面看一下网上下载的几张类图:
上面这两张图基本上展示了常用集合的基本关系。
一、Set与Map、List的关系
1、Set代表一种集合元素无序、集合元素不可重复的集合
2、Map代表一个有多个Key-Value对组成的集合,Key不能重复,Key之间无序
3、Set与Map表面上看起来没有什么关系,但是如果将Key、Value堪称一个对象,那么Map就相当于是Set
4、List按照元素的加入先后顺序保存元素,可以用过元素的精确位置获取元素;其余用法与Map相似,其key是一个int型的索引
SetMapEnumSetEnumMapSortedSetSortedMapTreeSetTreeMapNavigableSetNavigableMapHashSetHashMapLinkedHashSetLinkedHashMap
二、HashSet与HasnMap与HashTable
HashSet与HashMap分别是Set与Map的具体实现,在实际中经常使用的类。
二者有很多相似之处,采用哈市算法决定元素存放位置,能够保证快速的提取结合元素。
集合在存储对象的时候并没有真正的将对象放入集合中,而只是保留对该对象的引用而已
1、HashSet:
此类实现 Set 接口,由哈希表(实际上是一个 HashMap 实例)支持。它不保证 set 的迭代顺序;特别是它不保证该顺序恒久不变。此类允许使用null 元素。
此类为基本操作提供了稳定性能,这些基本操作包括 add、remove、contains 和 size,假定哈希函数将这些元素正确地分布在桶中。对此 set 进行迭代所需的时间与HashSet 实例的大小(元素的数量)和底层HashMap 实例(桶的数量)的“容量”的和成比例。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。
注意,此实现不是同步的。
public static void main(String[] args) { HashSet hs = new HashSet(4); hs.add("语文:80"); hs.add("数学:90"); hs.add("英语:95"); hs.add(null); System.out.print(hs); }[null, 数学:90, 语文:80, 英语:95]成功构建 (总时间: 0 秒)
2、HashMap:
基于哈希表的 Map 接口的实现。此实现提供所有可选的映射操作,并允许使用 null 值和 null 键。(除了非同步和允许使用 null 之外,HashMap 类与Hashtable 大致相同。)此类不保证映射的顺序,特别是它不保证该顺序恒久不变。
此实现假定哈希函数将元素适当地分布在各桶之间,可为基本操作(get 和 put)提供稳定的性能。迭代 collection 视图所需的时间与HashMap 实例的“容量”(桶的数量)及其大小(键-值映射关系数)成比例。所以,如果迭代性能很重要,则不要将初始容量设置得太高(或将加载因子设置得太低)。
HashMap 的实例有两个参数影响其性能:初始容量 和加载因子。容量 是哈希表中桶的数量,初始容量只是哈希表在创建时的容量。加载因子 是哈希表在其容量自动增加之前可以达到多满的一种尺度。当哈希表中的条目数超出了加载因子与当前容量的乘积时,则要对该哈希表进行rehash 操作(即重建内部数据结构),从而哈希表将具有大约两倍的桶数。
通常,默认加载因子 (.75) 在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查询成本(在大多数 HashMap 类的操作中,包括get 和put 操作,都反映了这一点)。在设置初始容量时应该考虑到映射中所需的条目数及其加载因子,以便最大限度地减少 rehash 操作次数。如果初始容量大于最大条目数除以加载因子,则不会发生 rehash 操作。
如果很多映射关系要存储在 HashMap 实例中,则相对于按需执行自动的 rehash 操作以增大表的容量来说,使用足够大的初始容量创建它将使得映射关系能更有效地存储。
注意,此实现不是同步的
public static void main(String[] args) { HashMap<String, Double> hm = new HashMap<String, Double>(); hm.put("语文", Double.valueOf(80)); hm.put("数学", Double.valueOf(90)); hm.put("英语", Double.valueOf(95)); System.out.print(hm); }{语文=80.0, 英语=95.0, 数学=90.0}成功构建 (总时间: 0 秒)
3、HashTable:
此类实现一个哈希表,该哈希表将键映射到相应的值。任何非 null
对象都可以用作键或值。
为了成功地在哈希表中存储和获取对象,用作键的对象必须实现 hashCode
方法和 equals
方法。
Hashtable
的实例有两个参数影响其性能:初始容量 和加载因子。容量 是哈希表中桶 的数量,初始容量 就是哈希表创建时的容量。注意,哈希表的状态为open:在发生“哈希冲突”的情况下,单个桶会存储多个条目,这些条目必须按顺序搜索。加载因子 是对哈希表在其容量自动增加之前可以达到多满的一个尺度。初始容量和加载因子这两个参数只是对该实现的提示。关于何时以及是否调用 rehash 方法的具体细节则依赖于该实现。
通常,默认加载因子(.75)在时间和空间成本上寻求一种折衷。加载因子过高虽然减少了空间开销,但同时也增加了查找某个条目的时间(在大多数 Hashtable 操作中,包括get 和put 操作,都反映了这一点)。
初始容量主要控制空间消耗与执行 rehash
操作所需要的时间损耗之间的平衡。如果初始容量大于 Hashtable 所包含的最大条目数除以加载因子,则永远 不会发生rehash
操作。但是,将初始容量设置太高可能会浪费空间。
如果很多条目要存储在一个 Hashtable
中,那么与根据需要执行自动 rehashing 操作来增大表的容量的做法相比,使用足够大的初始容量创建哈希表或许可以更有效地插入条目。
注意,此实现是同步的
public static void main(String[] args) { Hashtable<String, Double> ht = new Hashtable<String, Double>(); ht.put("语文", Double.valueOf(80)); ht.put("数学", Double.valueOf(90)); ht.put("英语", Double.valueOf(95)); System.out.print(ht); }{语文=80.0, 英语=95.0, 数学=90.0}成功构建 (总时间: 0 秒)
三、TreeSet与TreeMap
1、TreeMap:
基于红黑树(Red-Black tree)的 NavigableMap
实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的Comparator
进行排序,具体取决于使用的构造方法。
此实现为 containsKey、get、put 和 remove 操作提供受保证的 log(n) 时间开销。这些算法是 Cormen、Leiserson 和 Rivest 的Introduction to Algorithms 中的算法的改编。
注意,如果要正确实现 Map 接口,则有序映射所保持的顺序(无论是否明确提供了比较器)都必须与 equals 一致。(关于与 equals 一致 的精确定义,请参阅Comparable 或Comparator)。这是因为Map 接口是按照 equals 操作定义的,但有序映射使用它的compareTo(或compare)方法对所有键进行比较,因此从有序映射的观点来看,此方法认为相等的两个键就是相等的。即使排序与 equals 不一致,有序映射的行为仍然是 定义良好的,只不过没有遵守Map 接口的常规协定。
注意,此实现不是同步的
public static void main(String[] args) { TreeMap<String, Double> tm = new TreeMap<String, Double>(); tm.put("语文", Double.valueOf(80)); tm.put("数学", Double.valueOf(90)); tm.put("英语", Double.valueOf(95)); System.out.print(tm); }{数学=90.0, 英语=95.0, 语文=80.0}成功构建 (总时间: 0 秒)
2、TreeSet:
基于 TreeMap
的 NavigableSet
实现。使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的Comparator
进行排序,具体取决于使用的构造方法。
此实现为基本操作(add
、remove
和 contains
)提供受保证的 log(n) 时间开销。
注意,如果要正确实现 Set
接口,则 set 维护的顺序(无论是否提供了显式比较器)必须与 equals 一致。(关于与 equals 一致 的精确定义,请参阅Comparable
或Comparator
。)这是因为Set
接口是按照equals
操作定义的,但TreeSet
实例使用它的 compareTo
(或 compare
)方法对所有元素进行比较,因此从 set 的观点来看,此方法认为相等的两个元素就是相等的。即使 set 的顺序与 equals 不一致,其行为也是 定义良好的;它只是违背了Set
接口的常规协定。
注意,此实现不是同步的
public static void main(String[] args) { TreeSet ts = new TreeSet(); ts.add("语文:85"); ts.add("数学:95"); ts.add("英语:90"); System.out.print(ts); }[数学:95, 英语:90, 语文:85]成功构建 (总时间: 0 秒)
四、LinkedHashSet与LinkedHashMap与LinkedList
1、LinkedHashSet:
有可预知迭代顺序的 Set 接口的哈希表和链接列表实现。此实现与 HashSet 的不同之外在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,即按照将元素插入到 set 中的顺序(插入顺序)进行迭代。注意,插入顺序不 受在 set 中重新插入的 元素的影响。(如果在s.contains(e) 返回true 后立即调用s.add(e),则元素e 会被重新插入到 sets 中。)
此实现可以让客户免遭未指定的、由 HashSet
提供的通常杂乱无章的排序工作,而又不致引起与TreeSet
关联的成本增加。使用它可以生成一个与原来顺序相同的 set 副本,并且与原 set 的实现无关:
void foo(Set s) { Set copy = new LinkedHashSet(s); ... }
如果模块通过输入得到一个 set,复制这个 set,然后返回由此副本决定了顺序的结果,这种情况下这项技术特别有用。(客户通常期望内容返回的顺序与它们出现的顺序相同。)
此类提供所有可选的 Set 操作,并且允许 null 元素。与 HashSet 一样,它可以为基本操作(add、contains 和remove)提供稳定的性能,假定哈希函数将元素正确地分布到存储段中。由于增加了维护链接列表的开支,其性能很可能会比HashSet 稍逊一筹,不过,这一点例外:LinkedHashSet 迭代所需时间与 set 的大小 成正比,而与容量无关。HashSet 迭代很可能支出较大,因为它所需迭代时间与其容量 成正比。
链接的哈希 set 有两个影响其性能的参数:初始容量 和加载因子。它们与 HashSet 中的定义极其相同。注意,为初始容量选择非常高的值对此类的影响比对HashSet 要小,因为此类的迭代时间不受容量的影响。
注意,此实现不是同步的。
public static void main(String[] args) { LinkedHashSet lhs = new LinkedHashSet(); lhs.add("语文:85"); lhs.add("数学:95"); lhs.add("英语:90"); System.out.print(lhs); }[语文:85, 数学:95, 英语:90]成功构建 (总时间: 0 秒)
2、LinkedHashMap
Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。此实现与 HashMap 的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序通常就是将键插入到映射中的顺序(插入顺序)。注意,如果在映射中重新插入 键,则插入顺序不受影响。(如果在调用m.put(k, v) 前m.containsKey(k) 返回了true,则调用时会将键k 重新插入到映射m 中。)
此实现可以让客户避免未指定的、由 HashMap
(及 Hashtable
)所提供的通常为杂乱无章的排序工作,同时无需增加与 TreeMap
相关的成本。使用它可以生成一个与原来顺序相同的映射副本,而与原映射的实现无关:
void foo(Map m) { Map copy = new LinkedHashMap(m); ... }
如果模块通过输入得到一个映射,复制这个映射,然后返回由此副本确定其顺序的结果,这种情况下这项技术特别有用。(客户通常期望返回的内容与其出现的顺序相同。)
提供特殊的构造方法
来创建链接哈希映射,该哈希映射的迭代顺序就是最后访问其条目的顺序,从近期访问最少到近期访问最多的顺序(访问顺序)。这种映射很适合构建 LRU 缓存。调用put 或get 方法将会访问相应的条目(假定调用完成后它还存在)。putAll 方法以指定映射的条目集迭代器提供的键-值映射关系的顺序,为指定映射的每个映射关系生成一个条目访问。任何其他方法均不生成条目访问。特别是,collection 视图上的操作不 影响底层映射的迭代顺序。
可以重写 removeEldestEntry(Map.Entry)
方法来实施策略,以便在将新映射关系添加到映射时自动移除旧的映射关系。
此类提供所有可选的 Map 操作,并且允许 null 元素。与 HashMap 一样,它可以为基本操作(add、contains 和remove)提供稳定的性能,假定哈希函数将元素正确分布到桶中。由于增加了维护链接列表的开支,其性能很可能比HashMap 稍逊一筹,不过这一点例外:LinkedHashMap 的 collection 视图迭代所需时间与映射的大小 成比例。HashMap 迭代时间很可能开支较大,因为它所需要的时间与其容量 成比例。
链接的哈希映射具有两个影响其性能的参数:初始容量和加载因子。它们的定义与 HashMap 极其相似。要注意,为初始容量选择非常高的值对此类的影响比对HashMap 要小,因为此类的迭代时间不受容量的影响。
注意,此实现不是同步的。
public static void main(String[] args) { LinkedHashMap<String, Double> lhm = new LinkedHashMap<String, Double>(); lhm.put("语文", Double.valueOf(85)); lhm.put("数学", Double.valueOf(95)); lhm.put("英语", Double.valueOf(90)); System.out.print(lhm); }{语文=85.0, 数学=95.0, 英语=90.0}成功构建 (总时间: 0 秒)
3、LinkedList
List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾get、remove 和insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。
此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作。
所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。
注意,此实现不是同步的。
public static void main(String[] args) { LinkedList ll = new LinkedList(); ll.add("语文:85"); ll.add("数学:95"); ll.add("英语:90"); System.out.print(ll); }[语文:85, 数学:95, 英语:90]成功构建 (总时间: 0 秒)
五、ArrayList与LinkedList与Vector与Stack
List接口的实现类最常用的也就这几个,其中Stack是继承与Vector,在此基础上加了五个方法(用于先进后出)
1、ArrayList
List 接口的大小可变数组的实现。实现了所有可选列表操作,并允许包括 null 在内的所有元素。除了实现 List 接口外,此类还提供一些方法来操作内部用来存储列表的数组的大小。(此类大致上等同于 Vector 类,除了此类是不同步的。)
size、isEmpty、get、set、iterator 和 listIterator 操作都以固定时间运行。add 操作以分摊的固定时间 运行,也就是说,添加 n 个元素需要 O(n) 时间。其他所有操作都以线性时间运行(大体上讲)。与用于 LinkedList 实现的常数因子相比,此实现的常数因子较低。
每个 ArrayList 实例都有一个容量。该容量是指用来存储列表元素的数组的大小。它总是至少等于列表的大小。随着向 ArrayList 中不断添加元素,其容量也自动增长。并未指定增长策略的细节,因为这不只是添加元素会带来分摊固定时间开销那样简单。
在添加大量元素前,应用程序可以使用 ensureCapacity 操作来增加 ArrayList 实例的容量。这可以减少递增式再分配的数量。
注意,此实现不是同步的
public static void main(String[] args) { ArrayList al = new ArrayList(3); al.add("语文:85"); al.add("数学:95"); al.add("英语:90"); System.out.print(al); }[语文:85, 数学:95, 英语:90]成功构建 (总时间: 0 秒)
2、LinkedList
List 接口的链接列表实现。实现所有可选的列表操作,并且允许所有元素(包括 null)。除了实现 List 接口外,LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法。这些操作允许将链接列表用作堆栈、队列或双端队列。
此类实现 Deque 接口,为 add、poll 提供先进先出队列操作,以及其他堆栈和双端队列操作。
所有操作都是按照双重链接列表的需要执行的。在列表中编索引的操作将从开头或结尾遍历列表(从靠近指定索引的一端)。
注意,此实现不是同步的
3、Vector
Vector 类可以实现可增长的对象数组。与数组一样,它包含可以使用整数索引进行访问的组件。但是,Vector 的大小可以根据需要增大或缩小,以适应创建 Vector 后进行添加或移除项的操作。
每个向量会试图通过维护 capacity 和 capacityIncrement 来优化存储管理。capacity 始终至少应与向量的大小相等;这个值通常比后者大些,因为随着将组件添加到向量中,其存储将按 capacityIncrement 的大小增加存储块。应用程序可以在插入大量组件前增加向量的容量;这样就减少了增加的重分配的量。
public static void main(String[] args) { Vector al = new Vector(3); al.add("语文:85"); al.add("数学:95"); al.add("英语:90"); System.out.print(al); }[语文:85, 数学:95, 英语:90]成功构建 (总时间: 0 秒)
4、Stack
Stack 类表示后进先出(LIFO)的对象堆栈。它通过五个操作对类 Vector 进行了扩展 ,允许将向量视为堆栈。它提供了通常的 push 和 pop 操作,以及取堆栈顶点的 peek 方法、测试堆栈是否为空的 empty 方法、在堆栈中查找项并确定到堆栈顶距离的search 方法。
public static void main(String[] args) { Stack sk = new Stack(); sk.push("语文:85"); sk.push("数学:95"); sk.push("英语:90"); System.out.print(sk); }[语文:85, 数学:95, 英语:90]成功构建 (总时间: 0 秒)
------------------------------------------------------------------------------------------------------------------------------------------------------
continue。。。。。。。。。。
- Java常用集合使用
- Java学习笔记44:常用集合使用
- Java常用集合元素使用小结
- Java集合-常用集合类
- 常用集合使用
- java常用方法集合
- Java常用集合详解
- Java常用集合类
- java常用集合接口
- Java常用集合比较
- java常用集合总结
- java常用集合类
- Java常用集合总结
- java常用集合总结
- Java常用集合总结
- java常用集合总结
- java常用集合
- Java常用集合比较
- opensips安装配置
- visual studio和vc的版本对应关系
- speex移植到crotex-M4,注意事项
- java基础学习笔记(七) ajax
- java.lang.IllegalStateException: Cannot call sendError() after the response has been committed错误
- Java常用集合使用
- 电信IT支撑概览-资源篇-提供资源
- Easily View Images From Terminal in Ubuntu
- CodeForces - 11A Increasing Sequence
- 对象的赋值
- Ubuntu下使用虚拟机安装Windows XP
- 网页上的视频缩略图
- The Phantom of the Opera-5、A letter for Raoul
- css实现背景图片拉伸