本文首发于个人我的博客:尾尾部落html
Iterator接口,这是一个用于遍历集合中元素的接口,主要包含hashNext(),next(),remove()三种方法。它的一个子接口LinkedIterator在它的基础上又添加了三种方法,分别是add(),previous(),hasPrevious()。也就是说若是是先Iterator接口,那么在遍历集合中元素的时候,只能日后遍历,被遍历后的元素不会在遍历到,一般无序集合实现的都是这个接口,好比HashSet,HashMap;而那些元素有序的集合,实现的通常都是LinkedIterator接口,实现这个接口的集合能够双向遍历,既能够经过next()访问下一个元素,又能够经过previous()访问前一个元素,好比ArrayList。java
List是元素有序而且能够重复的集合。 List的主要实现:ArrayList, LinkedList, Vector。 面试
ArrayList | LinkedList | Vector | |
---|---|---|---|
底层实现 | 数组 | 双向循环链表 | 数组 |
同步性及效率 | 不一样步,非线程安全,效率高 | 不一样步,非线程安全,效率高 | 同步,线程安全,效率低 |
特色 | 查询快,增删慢 | 查询慢,增删快 | 查询快,增删慢 |
默认容量 | 10 | / | 10 |
扩容机制 | int newCapacity = oldCapacity + (oldCapacity >> 1); //1.5 倍 | / | 2 倍 |
总结:算法
- ArrayList 和 Vector 基于数组实现,对于随机访问get和set,ArrayList优于LinkedList,由于LinkedList要移动指针。
Set集合中的对象不按特定的方式排序(存入和取出的顺序不必定一致),而且没有重复对象。 Set的主要实现类:HashSet, TreeSet。 数组
HashSet | TreeSet | LinkedHashSet | |
---|---|---|---|
底层实现 | HashMap | 红黑树 | LinkedHashMap |
重复性 | 不容许重复 | 不容许重复 | 不容许重复 |
有/无序 | 无序 | 有序,支持两种排序方式,天然排序和定制排序,其中天然排序为默认的排序方式。 | 有序,以元素插入的顺序来维护集合的连接表 |
时间复杂度 | add(),remove(),contains()方法的时间复杂度是O(1) | add(),remove(),contains()方法的时间复杂度是O(logn) | LinkedHashSet在迭代访问Set中的所有元素时,性能比HashSet好,可是插入时性能稍微逊色于HashSet,时间复杂度是 O(1)。 |
同步性 | 不一样步,线程不安全 | 不一样步,线程不安全 | 不一样步,线程不安全 |
null值 | 容许null值 | 不支持null值,会抛出 java.lang.NullPointerException 异常。由于TreeSet应用 compareTo() 方法于各个元素来比较他们,当比较null值时会抛出 NullPointerException异常。 | 容许null值 |
比较 | equals() | compareTo() | equals() |
当你把对象加入HashSet时,HashSet会先计算对象的hashcode值来判断对象加入的位置,同时也会与其余加入的对象的hashcode值做比较,若是没有相符的hashcode,HashSet会假设对象没有重复出现。可是若是发现有相同hashcode值的对象,这时会调用equals()方法来检查hashcode相等的对象是否真的相同。若是二者相同,HashSet就不会让加入操做成功。 hashCode()与equals()的相关规定:安全
总结: HashSet是一个通用功能的Set,而LinkedHashSet 提供元素插入顺序保证,TreeSet是一个SortedSet实现,由Comparator 或者 Comparable指定的元素顺序存储元素。微信
Map 是一种把键对象和值对象映射的集合,它的每个元素都包含一对键对象和值对象。 Map没有继承于Collection接口从Map集合中检索元素时,只要给出键对象,就会返回对应的值对象。 Map 的经常使用实现类:HashMap、TreeMap、HashTable、LinkedHashMap、ConcurrentHashMap数据结构
HashMap | HashTable | |
---|---|---|
底层实现 | 数组+链表 | 数组+链表 |
同步性 | 线程不一样步 | 同步 |
null值 | 容许 key 和 Vale 是 null,可是只容许一个 key 为 null,且这个元素存放在哈希表 0 角标位置 | 不容许key、value 是 null |
hash | 使用hash(Object key)扰动函数对 key 的 hashCode 进行扰动后做为 hash 值 | 直接使用 key 的 hashCode() 返回值做为 hash 值 |
容量 | 容量为 2^4 且容量必定是 2^n | 默认容量是11,不必定是 2^n |
扩容 | 两倍,且哈希桶的下标使用 &运算代替了取模 | 2倍+1,取哈希桶下标是直接用模运算 |
1. HashMap 的工做原理? 经过hash的方法,经过put和get存储和获取对象。存储对象时,咱们将K/V传给put方法时,它调用hashCode计算hash从而获得bucket位置,进一步存储,HashMap会根据当前bucket的占用状况自动调整容量(超过Load Facotr则resize为原来的2倍)。获取对象时,咱们将K传给get,它调用hashCode计算hash从而获得bucket位置,并进一步调用equals()方法肯定键值对。若是发生碰撞的时候,Hashmap经过链表将产生碰撞冲突的元素组织起来,在Java 8中,若是一个bucket中碰撞冲突的元素超过某个限制(默认是8),则使用红黑树来替换链表,从而提升效率。 2.get和put的原理吗?equals()和hashCode()的都有什么做用? 经过对key的hashCode()进行hashing,并计算下标( n-1 & hash),从而得到buckets的位置。若是产生碰撞,则利用key.equals()方法去链表或树中去查找对应的节点 3. HashMap 的长度为何是2的幂次方? 为了能让 HashMap 存取高效,尽可能较少碰撞,也就是要尽可能把数据分配均匀,每一个链表/红黑树长度大体相同。这个实现就是把数据存到哪一个链表/红黑树中的算法。多线程
HashMap实现了Map接口,不保障元素顺序。 TreeMap实现了SortedMap接口,是一个有序的Map。内部采用红黑树实现,红黑树是一种维护有序数据的高效数据结构并发
ConcurrentHashMap 和 Hashtable 的区别主要体如今实现线程安全的方式上不一样。 底层数据结构: JDK1.7的 ConcurrentHashMap 底层采用 分段的数组+链表 实现,JDK1.8 采用的数据结构跟HashMap1.8的结构同样,数组+链表/红黑二叉树。Hashtable 和 JDK1.8 以前的 HashMap 的底层数据结构相似都是采用 数组+链表 的形式,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突而存在的; 实现线程安全的方式(重要): ① 在JDK1.7的时候,ConcurrentHashMap(分段锁) 对整个桶数组进行了分割分段(Segment),每一把锁只锁容器其中一部分数据,多线程访问容器里不一样数据段的数据,就不会存在锁竞争,提升并发访问率。(默认分配16个Segment,比Hashtable效率提升16倍。) 到了 JDK1.8 的时候已经摒弃了Segment的概念,而是直接用 Node 数组+链表+红黑树的数据结构来实现,并发控制使用 synchronized 和 CAS 来操做。(JDK1.6之后 对 synchronized锁作了不少优化) 整个看起来就像是优化过且线程安全的 HashMap,虽然在JDK1.8中还能看到 Segment 的数据结构,可是已经简化了属性,只是为了兼容旧版本;② Hashtable(同一把锁) :使用 synchronized 来保证线程安全,效率很是低下。当一个线程访问同步方法时,其余线程也访问同步方法,可能会进入阻塞或轮询状态,如使用 put 添加元素,另外一个线程不能使用 put 添加元素,也不能使用 get,竞争会愈来愈激烈效率越低。
获取最新资讯,请关注微信公众号:南强说晚安