Java 拾遗二 『集合类』
Java 集合类
总结一下Java自带常用的集合类;
如果你发现有错误的地方,还请指正,以免误人误己,非常感谢。
集合类图
(参考: JDK 8, 非全量)
Iterable<T>
: 迭代器接口;实现该接口的对象允许”for-each loop”的形式遍历,也就是foreach。迭代器只能向前移动(专门用来遍历)。Collection<E>
: 集合层次结构中的根接口。一个集合表示一组对象,称其为元素。有些集合允许重复元素,有些集合不允许。一些是有序的,另一些是无序的。提供一些集合通用的方法,例如:int size();
,boolean add();
…等方法。
List 接口
有序,可重复,它关注的是索引,可以精确的按照索引查找、移除元素。提供
get(int index); remove(int index);
…等方法。
具体实现类
ArrayList<E>
:内部是使用数组的形式存储元素的,它查询、随机访问,效率特别高,但是添加、插入、删除、需要确保内部顺序、容量,所以效率较低。非线程安全LinkedList<E>
:内部是使用双向链表的数据结构储存元素,它与 ArrayList 恰恰相反,在添加、插入、删除方面没有容量问题,所以效率较高,但是查询,随机访问时需要遍历整个列表,所以效率非常低。非线程安全(还有一点,有人说它是无序,(╬ ̄皿 ̄)=○,它在物理内存中是无序的,但 在程序逻辑上它是有序,有序,有序的!)Vector<E>
: 它与 ArrayList 非常相像,但 它是线程安全的,还有一个就是当容量不足时,默认扩容100%,而ArrayList 默认是 50%,它线程同步都是使用synchronized 关键词修饰方法,在效率上肯定低于 ArrayList 。
Set 接口
不允许重复的一组集合, 无索引,不能快速随机访问,提供方法:
Iterator<E> iterator();
可以返回它的迭代器,用于遍历,等等。
具体实现类
HashSet<E>
: 无序, 不允许重复,其实看看它的源码,就会发现,内部实例一个 HashMap ,用它的 key 存放元素,而value,都是存放同一个的Object空对象,也就是说可以存放一个null
。非线程安全TreeSet<E>
: 有序, 内部使用红黑树 (二叉树的一种)的数据结构存储,不允许重复。虽然有序,但没有索引,只能通过遍历操作元素。非线程安全
Queue 接口
通常是先进先出
(但不一定必须是=.=)的一个集合,像排队一样,所以叫队列;有的叫阻塞队列(即:在获取元素时,如果队列为空,就会阻塞等待至队列不为空;在添加元素时,如果队列已满,就会阻塞等待队列可放入。),反之就叫非阻塞队列。
它提供方法:add();
向队列添加元素,如果队列已满抛出 IllegalStateException ,peek();
检查列头是否为空,poll();
获取并移除列头的元素,等等
具体实现类
ArrayBlockingQueue<E>
: 使用数组实现的一个阻塞队列 , 似乎队列设计出来就是为了多线程使用,但它读写都是共用一个锁=。=。LinkedBlockingQueue<E>
: 内部使用单向链表实现的阻塞队列,与 ArrayBlockingQueue 不同,读写锁分离。
Map 类图
Map接口
Map 是一组以key的hashCode映射value的组合,通过key可以快速获得其映射的value,key是不能重复的,如果重复将会覆盖掉上一个映射。提供方法:
V put(K key, V value)
映射一组key跟value到集合,V get(Object key)
通过key获得其映射的value,void clear()
清除所有映射关系,等。
它跟 Iterable,Collection 都毫无关系,硬要说有,Map要有key才能访问对应的value,需要遍历所有的话,Map 提供Set<K> keySet();
返回一个包含所有key的Set;如果只需遍历value,提供Collection values();
返回一个包含所有value的Collection。
具体实现类
HashMap<K,V>
: 无序,可以有一个 key 为null
的Map,多次放入会覆盖上一个,非线程安全。Hashtable<K,V>
: 无序,不允许 key 为null
的Map,放入null
会抛出空指针异常, 线程安全,只是单纯使用synchronize
关键字实现。有人吐槽它的名字么?我就是我~ 是颜色不一样的烟火=.=TreeMap<K,V>
: 它的key是有序的, 内部红黑树数据结构存储元素 ,非线程安全。ConcurrentHashMap<K,V>
: 无序,同样不允许 key 为null
的Map, 线程安全,它采用分段锁的形式实现,把整个列表,分成若干部分,写入时锁住修改的部分,这样其它其他线程仍然可以操作没有锁住的部分,大大提高并发数,读取时不加锁,其value使用了volatile
关键字修饰,使得在不加锁的情况下,多线程读取数据总是最新的。