List特点:元素有放入顺序,元素可重复
Map特点:元素无放入顺序,元素可重复, 元素按键值对存储
Set特点:元素无放入顺序,元素不可重复(注意:元素虽然无放入顺序,但是元素在set中的位置是有该元素的HashCode决定的,其位置其实是固定的)
HashSet和TreeSet区别:
HashSet是哈希表实现的,数据无序的, 可以有一个null,放入对象必须实现Hash Code方法。
TreeSet是二叉树实现, 数据自动排序好, 不允许放入null。
ArrayList,Vetor和LinkedList区别
ArrayList:基于动态数组实现;
内存存储空间连续,查询快,插入慢,删除慢;
线程异步,不安全;
初始化容量后扩原来1.5 倍;不可以设置增长因子。
Vetor: 基于数组实现;
内存存储空间连续,查询快,插入慢,删除慢;
线程桐步,安全;
初始化容量后扩原来2 倍;可以设置增长因子。
LinkedList:基于双向链表实现,
要移动指针,查询性能低,插入快,删除快;
非线程安全,
ArrayList,Vetor 都为可伸缩的数组,可动态的改变数组长度。
HashMap和HashTable与ConcurrentHashMap的区别;
HashMap:允许为空键值;线程不同步,不安全;使用Enumeration;键的HashCode值存储数据,hash数组默认值为16,且为2的指数。
HashTable 不允许有空键值;线程安全;使用Iterator;hash数组默认大小是11,增长方式是old*2+1.
ConcurrentHashMap:线程安全,锁分段技术,并发性能好。
HashMap和HashTable的区别;
HashMap和Hashtable的底层实现都是数组+链表结构实现
1: 两者最主要的区别在于Hashtable是线程安全,而HashMap则非线程安全
Hashtable的实现方法里面都添加了synchronized关键字来确保线程同步,因此相对而言HashMap性能会高一些,我们平时使用时若无特殊需求建议使用HashMap,在多线程环境下若使用HashMap需要使用Collections.synchronizedMap()方法来获取一个线程安全的集合 (Collections.synchronizedMap()实现原理是Collections定义了一个SynchronizedMap的内部类,这个类实现了Map接口,在调用方法时使用synchronized来保证线程同步,当然了实际上操作的还是我们传入的HashMap实例,简单的说就是Collections.synchronizedMap()方法帮我们在操作HashMap时自动添加了synchronized来实现线程同步,类似的其它Collections.synchronizedXX方法也是类似原理)
2: HashMap可以使用null作为key,而Hashtable则不允许null作为key
虽说HashMap支持null值作为key,不过建议还是尽量避免这样使用,因为一旦不小心使用了,若因此引发一些问题,排查起来很是费事HashMap以null作为key时,总是存储在table数组的第一个节点上
3: HashMap是对Map接口的实现,HashTable实现了Map接口和Dictionary抽象类
4: HashMap的初始容量为16,Hashtable初始容量为11
两者的填充因子默认都是0.75
HashMap扩容时是当前容量翻倍即:capacity*2,
Hashtable扩容时是容量翻倍+1即apacity*2+1.
5: Hashtable计算hash是直接使用key的hashcode对table数组的长度直接进行取模
int hash = key.hashCode();
intindex = (hash & 0x7FFFFFFF) %tab.length;
HashMap计算hash对key的hashcode进行了二次hash,以获得更好的散列值,然后对table数组长度取摸
static int hash(int h){
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
static int indexFor(int h, int length) {
return h & (length-1);
}
HashSet和HashMap、Hashtable的区别:
HashSet不是key value结构,仅仅是存储不重复的元素,相当于简化版的HashMap,只是包含HashMap中的key而已
HashSet内部就是使用HashMap实现,只不过HashSet里面的HashMap所有的value都是同一个Object而已,因此HashSet也是非线程安全的,至于HashSet和Hashtable的区别,HashSet就是个简化的HashMap的
HashMap底层实现:
从结构实现来讲,HashMap是数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的,(1) HashMap:它根据键的hashCode值存储数据,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历顺序却是不确定的。 HashMap最多只允许一条记录的键为null,允许多条记录的值为null。HashMap非线程安全,即任一时刻可以有多个线程同时写HashMap,可能会导致数据的不一致。如果需要满足线程安全,可以用Collections的synchronizedMap方法使HashMap具有线程安全的能力,或者使用ConcurrentHashMap。
(2) Hashtable:Hashtable是遗留类,很多映射的常用功能与HashMap类似,不同的是它承自Dictionary类,并且是线程安全的,任一时间只有一个线程能写Hashtable,并发性不如ConcurrentHashMap,因为ConcurrentHashMap引入了分段锁。Hashtable不建议在新代码中使用,不需要线程安全的场合可以用HashMap替换,需要线程安全的场合可以用ConcurrentHashMap替换。
(3) LinkedHashMap:LinkedHashMap是HashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的,也可以在构造时带参数,按照访问次序排序。
(4) TreeMap:TreeMap实现SortedMap接口,能够把它保存的记录根据键排序,默认是按键值的升序排序,也可以指定排序的比较器,当用Iterator遍历TreeMap时,得到的记录是排过序的。如果使用排序的映射,建议使用TreeMap。在使用TreeMap时,key必须实现Comparable接口或者在构造TreeMap传入自定义的Comparator,否则会在运行时抛出java.lang.ClassCastException类型的异常。
对于上述四种Map类型的类,要求映射中的key是不可变对象。不可变对象是该对象在创建后它的哈希值不会被改变。如果对象的哈希值发生变化,Map对象很可能就定位不到映射的位置了。