一、Collection和Collections区别
Collection是一个集合接口。是list,set等的父接口。
Collections是一个包装类。
二、Set和List区别
相同点:
两者都继承自Collection接口,都是用来存储一组相同类型的元素的。
不同点:
List 元素有放入顺序,元素可重复。顺序是先放入的元素排在前面。
Set 元素无放入顺序,元素不可重复。
三、ArrayList和LinkedList和Vector的区别
三者都实现了List接口,使用方式也类似,主要区别在于因为实现方式的不同,所以对不同的操作具有不同的效率。
ArrayList
是一个可改变大小的数组,默认容量(DEFAULT_CAPACITY):10,最大容量:2^31-1。
扩容机制:1.5倍扩容。当元素数量大于默认容量(DEFAULT_CAPACITY)时扩容为原来的1.5倍。使用Arrays.copyOf()方法复制一份。
属于强同步类;如果程序是线程安全(没有在对线程之间共享同一个集合/对象),ArrayList是更好的选择。
使用了transient关键字进行存储优化;实现了writeObject(只保存非null的数组位置上的数据)。
提供了fast-fail机制;可以提供弱一致性。
默认的初始容量非常小,如果可以预估数据量的话,可以分配一个较大的初始值,这样可以减少调整大小的开销。
LinkedList
是一个双链表,数据量大的情况下,在添加和删除元素上比ArrayList性能好,但是在get与set方面若于ArrayList.
其实现了Queue接口,改接口比List提供了更多的方法,包括offer(),peek(),poll()等。
Vector
与ArrayList类似,但属于强同步类。扩增时每次请求其大小的双倍空间。
在多线程场景中可以直接使用Vector类,也可以使Collections.synchronizedList(List list)来返回一个线程安全的List. 区别在于:
1、synchronizedList有很好的扩展和兼容功能,可以将所有的List的子类转换成线程安全的类;
2、synchronizedList进行遍历时需要手动进行同步处理。(有listIterator 和 listIterator(int index)并没有做同步处理)
3、synchronizedList可以制定锁的对象,没有写入是默认是this;Vector只能是this
4、synchronizedList扩展方式是0.5倍;vector扩展方式是2倍;
四、HashMap、HashTable、ConcurrentHashMap区别
HashTable
线程安全,多线程并发条件下可以直接使用;
基于陈旧的Dirctionary类继承;
不允许出现key或者value为null值;
初始大小为11,增加为old*2+1;
不支持Iterator遍历;
缺点:
在单线程中无需做线程控制,运行效率更高;
在多线程中,synchronized会造成线程饥饿、死锁;保证线程安全可以使用ConcurrentHashMap
HashMap
结构:
jdk1.8之前,使用的是【数组+链表】的方式,1.8之后使用的【链表+红黑树】
默认长度(threshold):16,最大长度 2^30
默认加载因子(loadFactor):0.75f
默认临界值(threshold*loadFactor):16*0.75=12
链表转 红黑树 的阈值(TREEIFY_THRESHOLD):8,当链表长度达到8时,链表转成 红黑树
扩容机制:2倍扩容
触发机制1:当元素个数超过临街临界值(threshold * loadFactor)后,数组长度扩容为两倍
触发机制2:添加元素时,所属节点的链表长度超过阈值(默认8)、节点长度小于64,数组长度扩容为原来的两倍。若所属节点的长度超过8,但是数组总数超过64,此时不会扩容,会将链表转成 红黑树。
特点:
非线程安全;
继承的抽象类AbstractMap实现了Map接口,实现了Iterator,支持fast-fail;
允许key和value为null;
HashMap中hash数组的默认大小是16,而且一定是2的指数;
设置初始值操作:
1、初始化时设置大小=expectedSize/0.75F+1.0F (如:想初始值为7,那么7/0.75F+1.0F=10)
可以通过Maps实现:Maps.newHashMapWithExpectedSize(7);
ConcurrentHashMap
线程安全:同HashMap一样使用通数组实现,不同的是对通数组进行分段,每一段上用锁进行保护;
五、同步代码块和同步方法的区别
1、同步代码块在锁定的范围上可能比同步方法小,一般来说锁的范围大小和性能是成反比的。
2、同步代码块可以更加精准的控制锁的作用域(从锁被获取到其被释放是时间),同步方法的锁的作用域就是整个方法。
3、静态代码块可以选择对哪个对象枷锁,但是静态方法只能给this对象加锁。
六、HashSet、TreeSet
HashSet
HashSet数据结构是一个HashMap,利用HashMap的key不能重复的特性来进行去重。
TreeSet
TreeSet是一个有序的集合,数据结构是一个NavigableMap,利用key来去重。
TreeSet继承AbstractSet,所以它具有Set属性;
TreeSet实现了NavigableSet,所以它支持一系列的导航方法,比如查找、指定目标最高匹配项;
TreeSet实现了Cloneable接口,可以被克隆
TreeSet基于TreeMap实现,支持两种排序:自然排序、根据创建TreeSet时提供的Comparator进行排序;
栗子:将元素按照名称进行排序
/**
* 集合-TreeSet
*/
public void myTreeSet() {
//进行排序
Set set = new TreeSet<>(new Comparator<Object>() {
@Override
public int compare(Object o1, Object o2) {
return ((String) o1).compareTo((String) o2);
}
});
set.add("username-刘小向");
set.add("username8-刘小向8");
set.add("username9-刘小向9");
set.add("username2-刘小向2");
set.add("username5-刘小向5");
set.add("username6-刘小向6");
set.add("123");
set.add("username3-刘小向3");
set.add("username4-刘小向4");
set.add("username7-刘小向7");
}
运行结果: