Iterable
Collection
List
ArrayList(有序可重复,非线程安全)
LinkedList(有序可重复,非线程安全,也实现了Queue接口)
Vector(有序可重复,线程安全,效率低)
Stack(有序可重复,线程安全,效率低)
Set
HashSet(无序不可重复,非线程安全)
LinkedHashSet(有序不可重复,非线程安全)
TreeSet(有序不可重复,非线程安全)
Queue
PriorityQueue
Map
HashMap(无序,key不可重复,非线程安全)
LinkedHashMap(有序,key不可重复,非线程安全)
HashTable(无序,key不可重复,线程安全,效率低)
TreeMap(有序,key不可重复,非线程安全)
IdentityHashMap(无序,key可重复,非线程安全)
HashSet
哈希表结构,内部用HashMap的实例来实现,只存放key,value是一个无用的随机对象。add(key)的过程是HashMap的put(key, 随机value对象)的过程,没有取的方法,只能由HashSet生成迭代器,迭代出内部的全部元素,实际是遍历了HashMap的Entry数组且每次只取出key。
HashMap
哈希表结构,内部实现一个内部类Entry,看成链表结点的实现,有key,value,next等属性,内部建立一个默认长度为16的Entry数组,长度可指定。
put(key, value)的过程是根据用户给出的key,通过哈希算法计算出一个int值,即int hash = hash(key.hashCode()),而后用hash与表长取余,实际得到了Entry数组的下标,而后判断下标处的值,若没有值则根据用户给出的key、value创建一个Entry对象存入该位置,若有值则将用户给的key与该Entry的key对比,若相同由于key不可重复,用用户给的value替换当前Entry的value,若不同根据当前Entry的next,将用户给的key与next指向的下一个Entry的key继续比较,若找到相同的同上,若未找到相同的则创建新的Entry对象,并使用单链表的头插法插入新的结点;get(key)的过程是首先根据key生成哈希地址,然后到地址处比较key,若相同返回对应的value,若不同返回null。
由于key不可重复,在插入元素时有一个key的比较过程,使用equals方法。该方法默认比较的是对象的引用,除了java已经覆写过equals方法的类外,其它的类做key都必须先覆写equals方法,保证比较的是对象的内容而非引用。同理hashCode方法默认是根据对象的引用生成而非内容,如两个内容相同但引用不同的对象,被看成是相同的key,但很可能产生不同的hashCode,连对比key的可能都没有。由此重写equals与重写hashCode是一起的。String的equals与hashCode都已被重写。一切取决于字符串的内容,而不再是对象的引用,通常用String类型作为key。
当哈希表的长度不够时要对其扩大,HashMap哈希表长度默认为16,最大长度为2的30次方,扩充因子为0.75f。当哈希表中元素个数 >= 哈希表的长度 * 0.75f时,会自动将表长度扩大为当前表长的一倍。由于每次扩容都要重新计算表内已存元素的位置导致影响性能,由此应尽量避免扩容,在定义HashMap时尽量不要使用默认的长度。
备注:
1、在重写对象的hashCode时,必须以该对象的某个不会被改变的属性为基准,否则对象的属性改变,hashCode值也会改变,会出现前后不一致的现象。
2、equals只能用于对象,默认比较的是引用。java规范建议重写对象的equals方法,使其用于比较对象的内容。==是java的关系运算符,引用类型比较的是引用,基本类型比较的是值。
3、key、value均可为null,key为null时不调用hash方法,直接存在Entry下标为0的位置。由于key不可重复,所有的键值对中只可能有一个key = null的键值对,但可有多个value = null的键值对。