转载自:http://jiangzhengjun.iteye.com/blog/553191
1、Java容器类库的简化图,下面是集合类库更加完备的图。包括抽象类和遗留构件(不包括Queue的实现):
2、ArrayList初始化时不可指定容量,如果以new ArrayList()方式创建时,初始容量为10个;如果以new ArrayList(Collection c)初始化时,容量为c.size()*1.1,即增加10%的容量;当向ArrayList中添加一个元素时,先进行容器的容量调整,如果容量不够时,则增加至原来的1.5倍加1,再然后把元素加入到容器中,即以原始容量的0.5倍比率增加。
3、Vector:初始化时容量可以设定,如果以new Vector()方式创建时,则初始容量为10,超过容量时以2倍容量增加。如果以new Vector(Collection c)方式创建时,初始容量为c.size()*1.1,超过时以2倍容量增加。如果以new Vector(int initialCapacity, int capacityIncrement),则以capacityIncrement容量增加。
4、集合特点:
- List:保证以某种特定插入顺序来维护元素顺序,即保持插入的顺序,另外元素可以重复。
- ArrayList:是用数组实现的,读取速度快,插入与删除速度慢(因为插入与删除时要移动后面的元素),适合于随机访问。
- Vector:功能与ArrayList几乎相同,也是以数组实现,添加,删除,读取,设置都是基于线程同步的。
- LinkedList:双向链表来实现,删除与插入速度快,读取速度较慢,因为它读取时是从头向尾(如果节点在链的前半部分),或尾向头(如果节点在链的后半部分)查找元素。因此适合于元素的插入与删除操作。
- Set:维持它自己的内部排序,随机访问不具有意义。另外元素不可重复。
-
HashSet:是最常用的,查询速度最快,因为 内部以HashMap来实现,所以插入元素不能保持插入次序。
- LinkedHashSet:继承了HashSet,保持元素的插入次序,因为内部使用LinkedHashMap实现,所以能保持元素插入次序。
-
TreeSet:基于TreeMap,生成一个总是处于排序状态的set,它实现了SortedSet接口,内部以 TreeMap来实现
- TreeMap:键以某种排序规则排序,内部以red-black(红-黑)树数据结构实现,实现了SortedMap接口,具体可参《RED-BLACK(红黑)树的实现TreeMap源码阅读 》
- HashMap: 以哈希表数据结构实现,查找对象时通过哈希函数计算其位置,它是为快速查询而设计的,其内部定义了一个hash表数组(Entry[] table),元素会通过哈希转换函数将元素的哈希地址转换成数组中存放的索引,如果有冲突,则使用散列链表的形式将所有相同哈希地址的元素串起来,可能通过查看HashMap.Entry的源码它是一个单链表结构。
- Hashtable:也是以哈希表数据结构实现的,解决冲突时与HashMap也一样也是采用了散列链表的形式,不过性能比HashMap要低。
- LinkedHashMap:继承HashMap,内部实体LinkedHashMap.Entry继承自HashMap.Entry,LinkedHashMap.Entry在HashMap.Entry的基础上新增了两个实体引用(Entry before, after),这样实体可以相互串链起来形成链,并且在LinkedHashMap中就定义了一个头节点(Entry header)用来指向循环双向链的第一个元素(通过after指向)与最后一个元素(通过before指向)。在添加一个元素时,先会通过父类HashMap将元素加入到hash表数组里,然后再会在链尾(header.before指向位置)添加(当然这一过程只是调整LinkedHashMap.Entry对象内部的before, after而已,而不是真真创建一个什么新的链表结构向里加那样);删除先从hash表数组中删除,再将被删除的元素彻底的从双向链中断开。其实在链中添加与删除操作与LinkedList是一样的,可以参考《Java集合框架之LinkedList及ListIterator实现源码分析 》
5、Hashtable和HashMap的区别:
- Hashtable中的方法是同步的,而HashMap中的方法在缺省情况下是非同步的。在多线程应用程序中,我们应该使用Hashtable;而对于HashMap,则需要额外的同步机制。但HashMap的同步问题可通过Collections的一个静态方法得到解决:Map Collections.synchronizedMap(Map m),当然与可以自己在使用地方加锁。
- 在HashMap中,可以允许null作为键,且只可以有一个,否则覆盖,但可以有一个或多个值为null。因为当get()方法返回null值时,即可以表示 HashMap中没有该键,也可以表示该键所对应的值为null,所以HashMap不能由get()方法来判断否存在某个键,而应该用containsKey()方法来判断;而Hashtable不允许null键与null值。
- HashTable使用Enumeration,HashMap使用Iterator。
- Hashtable是Dictionary的子类,HashMap是Map接口的一个实现类;
- HashTable中hash table数组默认大小是11,增加的方式是 int newCapacity = oldCapacity * 2 + 1;,即增加至2倍(而不是2倍加1,因为扩容是在增加元素前进行的,在扩容后会将新增元素放入容器中)。HashMap中hash数组的默认大小是16,而且一定是2的多少次方;另外两者的默认负载因子都是0.75。
- 求哈希地址与哈希地址转hash数组(Entry table[])索引方法不同:
HashTable直接使用对象的hashCode:
- int hash = key.hashCode();
-
- int index = (hash & 0x7FFFFFFF) % tab.length;
而HashMap重新计算hash值,而且用位运算&代替求模:
- int hash = hash(k);
- int i = indexFor(hash, table.length);
-
- static int hash(Object x) {
-
- int h = x.hashCode();
- h += ~(h << 9);
- h ^= (h >>> 14);
- h += (h << 4);
- h ^= (h >>> 10);
- return h;
- }
- static int indexFor(int h, int length) {
- return h & (length-1);
- }
HashMap实现图:
6、集合中键值是否允许null小结
- List:可以有多个null,可以有重复值。
-
HashSet:能插入一个null(因为内部是以 HashMap实现 ),忽略不插入重复元素。
-
TreeSet:不能插入null (因为内部是以 TreeMap 实现 ) ,元素不能重复,如果待插入的元素存在,则忽略不插入,对元素进行排序。
- HashMap:允许一个null键与多个null值,若重复键,则覆盖以前值。
- TreeMap:不允许null键(实际上可以插入一个null键,如果这个Map里只有一个元素是不会报错的,因为一个元素时没有进行排序操作,也就不会报空指针异常,但如果插入第二个时就会立即报错),但允许多个null值,覆盖已有键值。
- HashTable:不允许null键与null值(否则运行进报空指针异常)。也会覆盖以重复值。基于线程同步。
7、对List的选择:
- 对于随机查询与迭代遍历操作,数组比所有的容器都要快。
- 从中间的位置插入和删除元素,LinkedList要比ArrayList快,特别是删除操作。
- Vector通常不如ArrayList快,则且应该避免使用,它目前仍然存在于类库中的原因是为了支持过去的代码。
- 最佳实践:将ArrayList作为默认首选,只有当程序的性能因为经常从list中间进行插入和删除而变差的时候,才去选择LinkedList。当然了,如果只是使用固定数量的元素,就应该选择数组了。
8、对Set的选择:
- HashSet的性能总比TreeSet好(特别是最常用的添加和查找元素操作)。
- TreeSet存在的唯一原因是,它可以维持元素的排序状态,所以只有当你需要一个排好序的Set时,才应该使用TreeSet。
- 对于插入操作,LinkedHashSet比HashSet略微慢一点:这是由于维护链表所带来额外开销造成的。不过,因为有了链表,遍历LinkedHashSet会比HashSet更快。
9、对Map的选择:
- Hashtable和HashMap的效率大致相同(通常HashMap更快一点,所以HashMap有意取代Hashtable)。
- TreeMap通常比HashMap慢,因为要维护排序。
- HashMap正是为快速查询而设计的。
- LinkedHashMap比HashMap慢一点,因为它维护散列数据结构的同时还要维护链表。
10、Stack基于线程安全,Stack类是用Vector来实现的(public class Stack extends Vector),但最好不要用集合API里的这个实现栈,因为它继承于Vector,本就是一个错误的设计,应该是一个组合的设计关系。
11、Iterator对ArrayList(LinkedList)的操作限制:
- 刚实例化的迭代器如果还没有进行后移(next)操作是不能马上进行删除与修改操作的。
- 可以用ListIterator对集合连续添加与修改,但不能连续删除。
- 进行添加操作后是不能立即进行删除与修改操作的。
- 进行删除操作后可以进行添加,但不能进行修改操作。
- 进行修改后是可以立即进行删除与添加操作的。
12、当以自己的对象做为HashMap、HashTable、LinkedHashMap、HashSet 、LinkedHashSet 的键时,一定要重写hashCode ()与equals ()方法,因为Object的hashCode()是返回内存地址,且equals()方法也是比较内存地址,所以当要在这些hash集合中查找时,如果是另外new出的新对象是查不到的,除非重写这两个方法。因为AbstractMap类的containsKey(Object key)方法实现如下:
- if (e.hash == hash && eq(k, e.key))
- return true;
-
- static boolean eq(Object x, Object y) {
- return x == y || x.equals(y);
- }
String对象是可以准确做为键的,因为已重写了这两个方法。
因此,Java中的集合框架中的哈希是以一个对象查找另外一个对象,所以重写hasCode与equals方法很重要。
13、重写hashCode()与equals()这两个方法是针对哈希类,至于其它集合,如果要用public boolean contains(Object o)或containsValue(Object value)查找时,只需要实现equals()方法即可,他们都只使用对象的 equals方法进行比对,没有使用hashCode方法。
14、TreeMap/TreeSet:放入其中的元素一定要具有自然比较能力(即要实现java.lang.Comparable接口)或者在构造TreeMap/TreeSet时传入一个比较器(实现java.util.Comparator接口),如果在创建时没有传入比较器,而放入的元素也没有自然比较能力时,会出现类型转换错误(因为在没有较器时,会试着转成Comparable型)。
两种比较接口:
-
- public interface java.lang.Comparable {
- public int compareTo(Object o);
- }
-
- public interface java.util.Comparator {
- int compare(Object o1, Object o2);
- boolean equals(Object obj);
- }
15、Collection或Map的同步控制:可以使用Collections类的相应静态方法来包装相应的集合类,使他们具线程安全,如public static Collection synchronizedCollection (Collection c)方法实质返回的是包装后的SynchronizedCollection子类,当然你也可以使用Collections的synchronizedList、synchronizedMap、synchronizedSet方法来获取不同的经过包装了的同步集合,其代码片断:
- public class Collections {
-
-
-
- static Collection synchronizedCollection(Collection c, Object mutex) {
- return new SynchronizedCollection(c, mutex);
- }
-
- public static List synchronizedList(List list) {
-
- }
-
- static Set synchronizedSet(Set s, Object mutex) {
-
- }
-
- public static Map synchronizedMap(Map m) {
- return new SynchronizedMap(m);
- }
-
-
- static class SynchronizedCollection implements Collection, Serializable {
-
- Collection c;
- Object mutex;
-
-
- SynchronizedCollection(Collection c, Object mutex) {
- this.c = c;
- this.mutex = mutex;
- }
-
- public int size() {
- synchronized (mutex) {
- return c.size();
- }
- }
-
- public boolean isEmpty() {
- synchronized (mutex) {
- return c.isEmpty();
- }
- }
-
- }
-
- static class SynchronizedList
分享到:
相关推荐
### Java集合小结 #### 一、集合的概念与重要性 集合是Java编程语言中用于存储、管理和操作数据的一种重要工具。它提供了多种数据结构来适应不同的应用场景,从而有效地提高程序开发效率。从数据结构的角度来看,...
#### 小结 通过本文档的学习,我们可以了解到Spring框架中各种属性注入的基本方法。这些方法不仅限于基本数据类型和集合类型,还包括Bean之间的引用注入,这些功能大大增强了Spring框架的灵活性和扩展性,使得开发...
<artifactId>mysql-connector-java</artifactId> <version>8.0.29</version> </dependency> <!-- 其他依赖如 JUnit 可按需添加 --> </dependencies> ``` 3. **项目结构**:确保项目结构正确,以便于管理不同的...
#### 小结 通过以上介绍可以看出,Echarts提供了一系列强大的图表组件,使得开发者能够轻松地将复杂的统计数据以图表的形式展现出来。无论是简单的折线图、柱状图还是更为复杂的时间轴折线图,都能够通过简单的配置...
【Spring 框架学习小结】 Spring 是一个流行的 Java 应用开发框架,它以其控制反转(Inversion of Control, IOC)和面向切面编程(Aspect-Oriented Programming, AOP)为核心特性,被誉为轻量级框架。下面将详细...
**Collection接口**作为Java集合框架的基础部分,在Java编程中扮演着非常重要的角色。它定义了一系列用于处理或操作集合中元素的方法,是所有集合类的根接口。 ### 11.2 Collection接口简介 #### 1. Collection...
### Java基础知识小结 #### 1.1 `getPath()`、`getAbsolutePath()`、`getCanonicalPath()`的区别 在Java中,处理文件路径时经常会用到`getPath()`、`getAbsolutePath()`以及`getCanonicalPath()`这三个方法。它们...
Spring还支持对集合类型的注入,如`<set/>`、`<list/>`、`<map/>`和`<props/>`。这些标签可以方便地注入对象的集合属性,例如,`<entry>`标签用于在`<map/>`中配置键值对。 **Spring Annotation支持**: 在Spring ...
**JSTL(JavaServer Pages Standard Tag Library)小结** JSTL,全称为JavaServer Pages Standard Tag Library,是Java Web开发中常用的一套标准标签库,它为开发者提供了处理常见页面逻辑的功能,如迭代、条件判断...
#### 五、小结 本文详细介绍了Hibernate中基于XML配置的一对一、一对多及多对多关联映射的实现方法。通过这些配置,可以方便地处理不同实体之间的关联关系,从而更好地实现数据的存储和查询操作。在实际开发中,...
### 集合小结 Collection #### Java集合概述 Java中的集合是一组对象的组合,类似于C++标准模板库中的容器。但是与C++不同的是,Java集合不仅可以存储单一类型的数据,还可以存储不同类型的对象。这使得Java集合...
为了全面理解Java基础知识,本小结将按照给定的文件名,逐一解析关键知识点。 1. **Java基础知识** 这一部分通常包括Java语言的基础语法,如变量、数据类型、运算符、流程控制(if语句、switch、for、while循环等...
Form<ClinicItem> form = new Form<>("form"); add(new Component[]{form}); form.add(new Component[]{button}); ``` #### 四、Wicket配置与部署 1. **web.xml配置**:这是Wicket应用的重要配置文件,...
实现集合可以通过实现Collection接口来完成,Collection接口是Java集合框架中的一个接口,Collection接口的实现类有ArrayList、LinkedList等。Collection接口的常用方法有add、remove、contains等。 小结 本节课...
#### 七、小结 通过上述介绍可以看出,Struts2 框架为开发者提供了一套完善的解决方案,包括表单处理、数据验证、异常处理、国际化等重要功能,大大降低了 Web 开发的复杂度,提高了开发效率。对于希望使用 Java ...
例如,在使用集合框架时,我们可以声明一个`List`类型的变量,然后将其赋值为`ArrayList`、`LinkedList`等不同实现的具体实例,而无需关心具体是哪一种实现,因为所有实现都遵循相同的接口规范。 此外,多态也是...
这个“java课程小结.rar_北京理工大学JAVA课程”压缩包中包含的“课程小结”文件,很可能是教授精心编写的教学精华,旨在帮助学生巩固所学知识并为后续学习打下坚实基础。 在Java课程中,有几个核心概念和技术是必...