Java容器类型学习笔记

最近抽空把java.lang下面常用的那些容器类型(数据结构)复习了一下,这些东西是基础,平时使用的时候也可以很容易查得到,有些方法大概知道,但是总是弄混,如果可以记住那些重要方法,并且能够熟练使用的话,还是可以让编码过程变得容易很多。另外一个是实现机制,对于常用数据结构的实现机制,应该说是必须要熟知的。

另外,并发容器我之前整理过,放在这篇文章里。

Queue

add和offer的区别在于达到上限时add抛出异常,offer返回false;
remove和poll的区别在于,队列为空时前者抛出异常,后者返回空;
element和peek都返回队列头部元素,但是前者失败不抛出异常,后者返回空。

boolean add(E e);
boolean offer(E e);
 
E remove();
E poll();
 
E element();
E peek();
PriorityQueue,内部实现是一个Object[] queue承载的堆。

Deque,双端队列(double-ended queue),在Queue基础上,增加了这样几个方法:

void addFirst(E e);
void addLast(E e);
 
boolean offerFirst(E e);
boolean offerLast(E e);
 
E removeFirst();
E removeLast();
 
E pollFirst();
E pollLast();
 
E getFirst();
E getLast();
 
E peekFirst();
E peekLast();
 
boolean removeFirstOccurrence(Object o);
boolean removeLastOccurrence(Object o);
ArrayDequeue:数组实现,扩容策略是容量翻倍。
 
List

boolean add(E e);
boolean remove(Object o);
E get(int index);
E set(int index, E element);
void add(int index, E element);
E remove(int index);
ArrayList,扩容策略是(oldCapacity * 3)/2 + 1。

LinkedList,它除了实现自List接口外,还实现了Deque接口。

Vector,实现自List接口,内部实现是个数组,线程安全,扩容策略是(capacityIncrement > 0) ? (oldCapacity + capacityIncrement) : (oldCapacity * 2)。

Stack是Vector的子类,增加了一些栈的方法:

E push(E item)
E pop()
E peek()
boolean empty()
 

Map

boolean containsKey(Object key);
boolean containsValue(Object value);
 
V get(Object key);
V put(K key, V value);
V remove(Object key);
 
Set<K> keySet();
Collection<V> values();
Set<Map.Entry<K, V>> entrySet();

SotedMap接口,key是有序的map:

SortedMap<K, V> subMap(K paramK1, K paramK2);
SortedMap<K, V> headMap(K paramK);
SortedMap<K, V> tailMap(K paramK);
 
K firstKey();
K lastKey();
子接口NavigableMap,提供了一些根据某个key寻找它前面或者后面的key的方法。其中floorKey/celingKey表示的关系是小于等于/大于等于,lower/higher表示的关系是严格的小于/大于:

Map.Entry<K,V> floorEntry(K key)
K floorKey(K key)
Map.Entry<K,V> ceilingEntry(K key)
K ceilingKey(K key)
 
Map.Entry<K,V> lowerEntry(K key)
K lowerKey(K key)
Map.Entry<K,V> higherEntry(K key)
K higherKey(K key)
TreeMap是NavigableMap的直接实现子类,内部实现是一个红黑树。

EnumMap,结构是<K extends Enum<K>, V>,内部是通过一个K[] keyUniverse和一个Object[] vals来实现的。

HashMap,内部是数组+链表实现的,达到threshold = capacity * loadFactor时,扩容策略为:numKeysToBeAdded / loadFactor + 1。

HashTable,实现自Dictionary和Map,方法都是线程安全的。HashTable的put方法,value不可以为空,这是它和HashMap的一个不同;再有二者找桶的hash方法不同;最后则是threshold计算逻辑相同,但它的扩容策略不同:oldCapacity * 2 + 1。HashTable、HashMap和HashSet经常被放到一起比较。

Properties,是HashTable的子类,方法线程安全。

IdentityHashMap,比较key不是使用equals来比较,而是使用“==”来比较,只要地址不等(即不是同一个对象)即可共存,也就是说,key是可以重复的。

LinkedHashMap,在HashMap的基础上,又单独维护了一个双向循环链表。有一个重要参数是accessOrder,accessOrder为true时,每次调用get方法访问行为发生后,会把最近访问的对象移动到头部,而超出容量移除对象时,是从尾部开始的,利用它并且覆写boolean removeEldestEntry方法可以实现一个LRU的队列。

WeakHashMap,但是key是weak引用,在不被使用时自动清除,扩容策略:tab.length * 2。原理上看:Entry<K,V> extends WeakReference<K> implements Map.Entry<K,V>,因此entry是弱引用的实现类,关键方法是expungeStaleEntries,它在对这个map各种操作的时候都会被调用到,而这个方法里面也是靠监听key的ReferenceQueue这个队列的状态来确定是否真的没有对象引用了。

Set

boolean contains(Object o);
boolean add(E e);
boolean remove(Object o);

SortedSet,接口方法和SortedMap类似:

 
SortedSet<E> subSet(E fromElement, E toElement);
SortedSet<E> headSet(E toElement);
SortedSet<E> tailSet(E fromElement);
 
E first();
E last();
相应地,NavigableSet和NavigableMap类似,方法就不列出了。

TreeSet则和TreeMap类似,其实内部实现就是一个TreeMap。

HashSet,尤其注意的是,有两种实现,当构造方法参数小于3个时,内部使用HashMap,否则,使用LinkedHashMap。

RegularEnumSet和JumboEnumSet,前者是普通的枚举set(用位移来表示各种组合的可能,达到空间占用最小,最大不能超过64个枚举值),后者适合数量较大的枚举set(老老实实地使用对象数组)。

LinkedHashSet,其实和LinkedHashMap是一个东西。

BitSet,叫set但是没有实现set的接口。用比特位来存放某个数是否存在,比如仅仅一个long,64位,就可以存放0~63的数,内部实际的数据类型是long[]。

 
void flip(int bitIndex);
void flip(int fromIndex, int toIndex);
 
void set(int bitIndex);
void set(int fromIndex, int toIndex, boolean value);
 
void clear(int bitIndex);
 
int length();
int size();
其中size方法返回实际使用了的比特位数目;length方法返回逻辑意义上的长度(比如表示的数里面最大是80,那么加上0,它的逻辑意义上的长度就是81)。

扩容策略:Math.max(2 * words.length, wordsRequired)。

Dictionary

 
Enumeration<K> keys();
Enumeration<V> elements();
 
V get(Object key);
V put(K key, V value);
V remove(Object key);
已经被废弃了,用Map来实现相同功能。

最后这张图来自这个网站,对于从宏观上把握这些容器类型实在是太有帮助了:

时间: 2024-09-20 17:26:29

Java容器类型学习笔记的相关文章

Java中jqGrid 学习笔记整理——进阶篇(二)_java

相关阅读: Java中jqGrid 学习笔记整理--进阶篇(一) 本篇开始正式与后台(java语言)进行数据交互,使用的平台为 JDK:java 1.8.0_71 myEclisp 2015 Stable 2.0 Apache Tomcat-8.0.30 Mysql 5.7 Navicat for mysql 11.2.5(mysql数据库管理工具) 一.数据库部分 1.创建数据库 使用Navicat for mysql创建数据库(使用其他工具或直接使用命令行暂不介绍) 2. 2.创建表 双击打

java泛型的学习笔记[2]—实际使用

继上一文<java泛型的学习笔记[1]-基础知识>之后,本文将介绍泛型的一些应用和应用过程中遇到的问题. 在此之前,我们先给出一张类图:   1)泛型类型的子类型问题 我们首先来看这样一句代码.该行代码正确,因为Cat是Animal的子类型 Animal animal=new Cat();// 但是再看下一句代码: AarrayList<Animal> animals=new ArrayList<Cat>();//编译出错        这句代码编译出错,因为虽然因为C

java对象序列化学习笔记

java对象|笔记 目前网络上关于对象序列化的文章不少,但是我发现详细叙述用法和原理的文章太少.本人把自己经过经验总结和实际运用中的体会写成的学习笔记贡献给大家.希望能为整个java社区的繁荣做一点事情.    序列化的过程就是对象写入字节流和从字节流中读取对象.将对象状态转换成字节流之后,可以用java.io包中的各种字节流类将其保存到文件中,管道到另一线程中或通过网络连接将对象数据发送到另一主机.对象序列化功能非常简单.强大,在RMI.Socket.JMS.EJB都有应用.对象序列化问题在网

Java编程思想学习笔记——类型信息

前言 运行时类型信息(RTTI:Runtime Type Information)使得我们可以在程序运行时发现和使用类型信息. Java在运行时识别对象和类的信息的方式: (1)一种是RTTI,它假定我们在编译时已经知道了所有的类型. (2)另一种是反射机制,它允许我们在运行时发现和使用类的信息. 为什么需要RTTI 以使用了多态的类层次结构的例子举例: 如上图,泛型是基类Shape,而派生出来的具体类有Circle,Square和Triangle. 这是一个类层次结构图,基类位于顶部,而派生类

Java编程思想学习笔记——枚举类型

前言 关键字enum可以将一组具名的值有限集合创建一种为新的类型,而这些具名的值可以作为常规的程序组件使用. 正文 基本enum特性 调用enum的values()方法可以遍历enum实例,values()方法返回enum实例数组,且数组中元素保持在enum声明时的顺序. public class TestEnum { public static void main(String[] args) { Fruit[] values = Fruit.values(); for (Fruit frui

java.util包学习笔记一

笔记 学习java2SDK 1.4.0 java.util里边有几个重要的接口,列在这里作为学习的总结: 1 java.util.Enumeration有两个方法hasMoreElements(),nextElement().使用方法如下://打印向量v的所有元素for(Enumeratin e = v.elements(); e.hasMoreElements();){ System.out.println(e.nextElement().toString());}这里注意要调用nextEle

Java NIO 完全学习笔记(转)

本篇博客依照 Java NIO Tutorial 翻译,算是学习 Java NIO 的一个读书笔记.建议大家可以去阅读原文,相信你肯定会受益良多. 1. Java NIO Tutorial Java NIO,被称为新 IO(New IO),是 Java 1.4 引入的,用来替代 IO API的. Java NIO:Channels and Buffers 标准的 Java IO API ,你操作的对象是字节流(byte stream)或者字符流(character stream),而 NIO,你

Java软件开发学习笔记(二)

笔记 1. 相关知识1.1 Java编程语言是从一开始就支持软件本地化的第一个编程语言. 所有的字符串都使用Unicode 1.2 要本地化的内容: 数字 123,456.78 英国 ; 123.456,78 德国 货币 日期 3/22/61 美国 ; 22.03.1961 德国 March 22,1961 ; 英文 22. Marz 1961 德语 ; 1961年3月22日 中文 时间 文本 -> 图形用户界面(集中以上情况) 1.3 Locale类 locale, 简单来说是指语言和区域进行

Java软件开发学习笔记(一)

笔记 1. Java是一种现代的程序设计语言,并且生逢其时 Java语言拥有良好的特性(面向对象)和最好的价格(免费), 在最恰当的地方(在web上),又在最合适的时间(正好在web逐渐流行时)出现. 2. 1995年5月,第一版 1998年底,J2SDK 3. 抽象是计算中的关键概念 面向对象的程序设计集中于对抽象的识别和运用上 抽象是建立在分层上的 底层是编程语言,其上层是标准类库中的抽象,最上边的一层或若干层是由程序员建立的各种抽象 (每一层抽象都对实现为程序的系统提供一个较高层次的视角)