Java 集合类

总览

先放一张Java集合类的关系图(非原创)

Java集合框架图

类有点多,看的眼晕?我们来慢慢从头梳理一下。

图中四边为点细点的是接口,虚线的是抽象类。

Iterator

迭代器。从源码看Collection接口继承了Iterator接口,所以我们平时用到的ArrayList、LinkedList等都是实现了Iterator接口的。迭代器是用来遍历选择序列中的对象的,但是它只能单向移动。

1)使用方法iterator()要求容器返回一个Iterator。
2)使用hasNext()检查序列中时候还有元素。
3)使用next()获取序列中的下一个元素。
4)使用remove()将迭代器最新返回的元素删除。

重点在使用迭代器的时候如果遇到需要将当前获取到的元素从序列中移除,比如遍历一个List,不能使用List.remove(),而要使用迭代器的Iterator.remove()。

ListIterator

这是一个更加强大的Iterator的子类型,只能用于各种List类的访问。ListIterator可以双向移动

看一看源码中定义的方法就明白了:

boolean hasNext();
E next();
boolean hasPrevious();
E previous();
int nextIndex();
int previousIndex();
void remove();
void set(E e);//将最近返回的元素替换
void add(E e);//向下一个将要返回的元素前面插入新元素

Collection

Collection接口概括了序列的概念——一种存放一组对象的方式。一个独立元素的序列,这些元素都服从一条或多条规则。List必须按照插入的顺序保存元素,Set不能有重复的元素(这里先这样记着,这确实是Set的特点,其他后面再详细说)。Queue按照排队规则来确定对象产生的顺序(很简洁的用几个方法实现了队列的功能)。

在添加一组元素的时候建议使用Collections.addAll(..)。

public static <T> boolean addAll(Collection<? super T> c, T... elements)

Map

可能是图上有误,从源码看其实它和Collection接口并没有关系,两者互相独立。Map使用一组“键值对”(key-value)来储存元素,允许使用键来查找值。Map不能包含重复的key,但是可以包含相同的value。

List

这里只提ArrayList和LinkedList。

ArrayList & LinkedList

ArrayList的实现是基于动态对象数组,源码:

transient Object[] elementData;

LinkedList的实现是基于双向链表,适合用于实现Stack和Queue,链表节点的源码:

private static class Node<E> {
        E item;
        Node<E> next;
        Node<E> prev;

        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }

随机访问的时候,ArrayList的性能要优于LinkedList,因为ArrayList只需要提取下标对应的元素,而LinkedList需要通过链表一个个的往后查找。

在执行插入移除操作的时候,特别是频繁插入,量大的时候,LinkedList的性能要远优于ArrayList。对LinkedList来说,插入元素只需要调整前后元素的指针(上面的next和prev);而对ArrayList来说,插入移除操作不仅需要将后面的元素全部进行移动,还要在空间不足的时候进行动态扩展(新建一个更大的数组并把原来的数组copy过去)。

最佳的做法可能是将ArrayList作为默认首选,只有你需要使用额外的功能,或者当程序性能因为经常从表中间进行插入和删除而变差的时候,才去选择LinkedList。

Map

HashMap & HashTable

两者都是存储“键值对”(key-value)的散列表,都是采用拉链法实现的。
即使用Entry<K,V>数组来存放键值对(各自有静态内部类Entry,继承自Map.Entry),数组中每个槽位又是一个链表的头节点。笔者描述的不太清楚,看图就明了了。


来自HashMap的百度百科

添加和删除操作的实现:用key计算出hash值,以hash值为数组下标检查对应槽位是否存在Entry,若有,沿着链表对比key和Entry的key。若匹配到了,添加操作就变成覆盖原来的value值,删除操作就删除该节点。若匹配不到,添加操作就把该键值对插入到该链表表头,删除操作返回null。
这里有个区别,HashTable是直接使用key.hashCode()方法返回值作为hash值,而HashMap则要在HashMap.hash(Object key)方法中使用key.hashCode()返回值重新计算产生hash值:

static final int hash(Object key) {
        int h;
        return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
    }

在线程安全方面,HashTable几乎所有方法都加上了synchronized关键字实现线程安全,而HashMap没有,需要HashMap实现线程安全的话可以使用

Map Collections.synchronizedMap(Map m)

不过这两种都是锁住整个Map,而ConcurrentHashMap则使用分段加锁实现线程安全,在多线程时性能更好。

LinkedHashMap

LinkedHashMap继承自HashMap,增加了一个Entry链表来储存键值对的添加顺序,以便在遍历时按添加顺序遍历。应该只在程序功能有这方面要求时使用,不然额外维护一个链表需要耗费额外的资源。

TreeMap

TreeMap使用红黑树来实现的,按照键来进行排序。

Map的遍历

1、使用keySet(),在遍历返回的key获取对应的value。
2、使用entrySet(),直接或许每一组键值对,推荐

第一选择还是HashMap吧,除非有额外的功能需求。

Set

HashSet & TreeSet

HashSet内部用一个HashMap来实现功能,TreeSet则是封装了一个TreeMap。
怎么实现不重复元素,看下面几行源码就明白了:

private static final Object PRESENT = new Object();
······
public boolean add(E e) {
        return m.put(e, PRESENT)==null;
    }

参考:
jdk1.8.0中的源码
《Java编程思想》
JAVA集合类汇总
Java 集合系列14之 Map总结

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

推荐阅读更多精彩内容