java集合类

java集合提供两大接口衍生:Collection和Map接口

1.Collection接口包含一批对象的集合;

2.Map接口在Collection基础上,为每个对象指定key,并使用Entry保存每个key-value对,实现通过key快速定位到对象;

3.List类集合

     List接口继承自Collection,用于定义以列表形式存储的集合,List接口为集合中的每个对象分配了一个索引(index),标记该对象在List中的位置,并可以通过index定位到指定位置的对象。

4.List接口常用的实现类

       4.1ArrayList:基于数组来实现集合的功能,其内部维护了一个可变长的对象数组,集合内所有对象存储于这个数组中,并实现该数组长度的动态伸缩。

       4.2LinkedList:基于链表来实现集合的功能,其实现了静态类Node,集合中的每个对象都由一个Node保存,每个Node都拥有到自己的前一个和后一个Node的引用

注意:1)ArrayList随机访问高,基于数组实现可直接定位目标对象,ListedList需从头Node或尾Node遍历才能定位到目标对象。

2)linkedList在头/尾节点执行插入/删除操作的效率比ArrayList要高

3)ArrayList每次扩容的容量是当前的1.5倍,所以LinkedList所占的内存空间要更小一些

4)两者遍历效率接近,LinkedList遍历需要iterator方式,不使用get()方式,否则效率很低。

        4.3Vector:与ArrayList一样都是基于数组实现的集合,区别在于vector是线程安全(常用方法基本都是synchronized);vector可以定义数组长度扩容因子,ArrayList不能。

        4.4CopyOnWriteArrayList:可以认为ArrayList线程安全版,主要 CopyOnWriteArrayList在写操作会先复制出一个副本,在新的副本上执行操作,然后修改引用。这种机制让 CopyOnWriteArrayList可以对读操作不加锁,这就使CopyOnWriteArrayList的读效率远高于Vector。 CopyOnWriteArrayList的理念比较类似读写分离,适合读多写少的多线程场景。但要注意,CopyOnWriteArrayList只能保证数据的最终一致性,并不能保证数据的实时一致性,如果一个写操作正在进行中且并未完成,此时的读操作无法保证能读到这个写操作的结果。

注意:二者均是线程安全的、基于数组实现的List

Vector是【绝对】线程安全的,CopyOnWriteArrayList只能保证读线程会读到【已完成】的写结果,但无法像Vector一样实现读操作的【等待写操作完成后再读最新值】的能力

CopyOnWriteArrayList读性能远高于Vector,并发线程越多优势越明显

CopyOnWriteArrayList占用更多的内存空间

5.Map类集合

       将key和value封装至Entry对象中,Map存储的元素实际是Entry。调用keySet()和values()时才将keySet和values对象实例化。

Map接口常用实现类:

       5.1.HashMap:将Entry对象存储在数组中,通过哈希表实现对Entry的快速访问。每个Entry中key的哈希值决定Entry在数组中的位置。通过key快速找到Entry,获得key对应的value。如果两个不同key计算的index一样,也就是两个不同的key对应数组同一个位置(哈希冲突),HashMap处理冲突的方法是拉链法,也就说每个位置保存实际是一个Entry链表,链表中每个Entry都拥有指向链表中后一个Entry引用。当发生哈希冲突时,冲突的Entry追加至链表的头部。当HashMap寻址时发现某个Key对应数组index上有多个Entry,便会遍历该位置上Entry链表。直到找到。

       5.2.HashTable实现思路和HashMap一致,都是通过数组存储Entry,以key的哈希值计算Entry在数组中index,用拉链法解决哈希冲突。最大的区别HashTable是线程安全的

      5.3.ConcurrentHashMap:是HashMap线程安全版,比HashTable更加高效的并发性能。

       HashTable在读写会锁定整个Entry数组,所以数据越多性能越差。ConcurrentHashMap使用分离锁思路解决并发性能,将Entry数组拆分16个Segment中,通过Hash算法决定Entry应存储在那个Segment。这样实现写操作只对一个Segment加锁。提高并发写性能。

在读操作,ConcurrentHashMap绝大多数不需要加锁,其Entry中value是volatile,保证value被修改时线程可见性,无需加锁便实现线程安全的读操作。

HashEntry类

static final class HashEntry {

final int hash;

final K key;

volatile V value;

volatile HashEntry next;

}

      注意:ConcurrentHashMap保证读操作能获取到已存在Entry的value的最新值,同时也能保证读操作可获取到已完成的写操作的内容,但如果写操作是在创建一个新的Entry,那么在写操作没有完成时,读操作是有可能获取不到这个Entry的。

总结:1.三者数据存储机制原理基本一致

         2.HashMap不是线程安全的,多线程除了不能保证数据一致性,还可能在rehash阶段引发Entry链表成环,导致死循环

         3.HashTable线程安全,保证数据一致但性能问题,并发越多性能越差

         4.ConcurrentHashMap线程是线程安全的,使用分离锁和volatile方法极大提升读写性能,同时保证大多数情况下数据一致性。但不能绝对保证(一个线程向Map加入Entry还没结束之前,其他线程不能读到新加入的Entry)

        5.4LinkedHashMap 与HashMap一致,不同在于前者在Entry基础上增加到前一个插入和后一个插入Entry的引用,实现按照Entry插入顺序进行遍历。

        5.5TreeMap 基于红黑树实现Map,其Entry类拥有左右子节点和父节点的引用,同时记录自己的颜色

static final class Entry implements Map.Entry {

K key;

V value;

Entry left = null;

Entry right = null;

Entry parent;

boolean color = BLACK;

}

红黑树是高效的平衡二叉树,及任何结点值都大于左结点,小于右节点,所以TreeMap能够实现Entry排序和快速查找。

6.Set类集合

       set接口继承Collection,存储不含重复元素。每个Set内都有一个同类型Map实例,set把元素作为key存储在自己Map实例中,value则是一个空的Object。

Set的常用实现也包括 HashSet、TreeSet、ConcurrentSkipListSet等,原理和对应的Map实现完全一致

7.Queue/Deque类集合

        Queue和Deque接口继承Collection接口,实现FIFO(先进先出)的集合。二者的区别在于,Queue只能在队尾入队,队头出队,而Deque接口则在队头和队尾都可以执行出/入队操作

ConcurrentLinkedQueue是基于链表实现的队列,队列中每个Node拥有到下一个Node的引用。由于Node类的成员都是volatile的,所以ConcurrentLinkedQueue自然是线程安全的

面试题:

1.ArrayList和LinkedList有什么区别

        ArrayList是基于动态数组的结构,使用索引在数组中查找和读取速度很快,时间复杂度O(1),删除数据开销很大。LinkedList插入或删除效率高时间复杂度O(1),它不需要改变数组大小,也不需要装满后重新装入新数组。LinkedList需要更多的内存每个节点都会存储数据和前后节点的位置。

2.用过哪些Map类,都有什么区别,HashMap是线程安全的吗,并发下使用的Map是什么,他们内部原理分别是什么,比如存储方式,hashcode,扩容,默认容量等?

      2.1.HashMap线程不安全,允许有null值,HashTable线程安全,不允许有null值,效率低,每个方法都是synchronized

      2.2 HashMap将Entry存储在数组中,通过哈希值实现Entry快速访问,当产生HashMap冲突采用拉链法。

        2.3 ConcurrentHashMap是hashMap线程安全版,HashTable在读写锁定整个Entry数组性能差,ConcurrentHashMap使用分离锁思路解决并发性能,将Entry数组拆分16个Segment中,通过Hash算法决定Entry应存储在那个Segment。这样实现写操作只对一个Segment加锁提高并发写性能,在读操作时,value值通过volatile修饰的,达到线程可见性。

        2.4HashTable默认的初始大小为11,之后每次扩充为原来的2n+1。HashMap默认的初始化大小为16,之后每次扩充为原来的2倍。

3.JAVA8的ConcurrentHashMap为什么放弃了分段锁,有什么问题吗,如果你来设计怎么设计?

       JDK8放弃Segment分段锁,启用全新的方式:CAS算法,其实底层依然使用数组”+链表+红黑树方式思想。

4. 有没顺序的Map实现类,如果有,他们是怎么保证有序的 ?

       TreeMap和LinkedHashMap是有序的。(TreeMap默认升序,LinkedHashMap则记录了插入顺序)。

5.hashset与hashMap区别

        HashSet实现了Set接口,它不允许集合中有重复的值,当我们提到HashSet时,第一件事情就是在将对象存储在HashSet之前,要先确保对象重写equals()和hashCode()方法,这样才能比较对象的值是否相等,以确保set中没有储存相等的对象。如果我们没有重写这两个方法,将会使用这个方法的默认实现。

public boolean add(Object o)方法用来在Set中添加元素,当元素值重复时则会立即返回false,如果成功添加的话会返回true。

HashSet和HashMap的区别

*HashMap**HashSet*

HashMap实现了Map接口HashSet实现了Set接口

HashMap储存键值对HashSet仅仅存储对象

使用put()方法将元素放入map中使用add()方法将元素放入set中

HashMap中使用键对象来计算hashcode值HashSet使用成员对象来计算hashcode值,对于两个对象来说hashcode可能相同,所以equals()方法用来判断对象的相等性,如果两个对象不同的话,那么返回false

HashMap比较快,因为是使用唯一的键来获取对象HashSet较HashMap来说比较慢

参考:http://weizhan.51cto.com/article/view/591c117ef2dd875f6f298f42?is_share=1

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容