一、概要
Java集合是Java语言最基础也很重要的一部分知识,很多公司的面试官面试Java开发的时候都会专门考察Java集合方面的知识。网上已经有很多Java集合系列的文章,这里我也对Java集合大家族各个主要成员做个详细系统的介绍。本篇是总序,介绍集合大家族的主要成员,后面会介绍一些具体的集合实现类。
二、Java集合大家庭
Java集合类存放在java.util包中,工具包中其实包含了一些很重要的类,比如集合。如图所示,这是集合家族的简单示意图,集合主要有两大类,分别是Collection和Map,这是两种不一样的存储方式。Collection是代表一组对象,包括多个元素(也可能是空元素),而Map则是键值对的存在方式,一个键对应一个值。
Collection是集合层级结构的根,有一系列的子接口,比如List和Set,它规范了一系列行为。比如以下规范:
public boolean add(E object);
增加元素,返回值如果是true则是成功添加
public boolean addAll(Collection<? extends E> collection);
尝试添加所有元素到集合中,返回值同上
public void clear();
清空集合
public boolean contains(Object object);
是否包含指定的元素
public boolean containsAll(Collection<?> collection);
是否包含参数集合中所有元素
public boolean equals(Object object);
比较两个对象(集合)是否相同
public int hashCode();
返回hash码,如果对象相同,则返回的hash码也相同
public boolean isEmpty();
判断集合是否是空的(没有数据)
public Iterator<E> iterator();
是个迭代器,循环获取数据用的
public boolean remove(Object object);
删除特定的数据
public boolean removeAll(Collection<?> collection);
删除所有数据
public boolean retainAll(Collection<?> collection);
个人理解是元素删除,只是删除的是除了参数集合中的其他元素
public int size();
返回集合中元素的数量
public Object[] toArray();
集合转换成数组
public <T> T[] toArray(T[] array);
将集合中的元素放在一个特定的数组中T[],如果这个T[]够大则放进去,如果不够大,则重新创建新的数组
List是Collection的一个直接子接口,List中的元素是有序的,每个元素都有一个下标,可以通过下标获取到元素,第一个下标是0,通常允许重复元素。List的具体实现有ArrayList,LinkedList等,List的源码如下:
public void add(int location, E object);
插入特定元素到特定位置
public boolean add(E object);
添加一个元素到集合尾部
public boolean addAll(int location, Collection<? extends E> collection);
在特定的位置插入整个集合
public boolean addAll(Collection<? extends E> collection);
在集合尾部插入整个集合
public void clear();
清空集合元素
public boolean contains(Object object);
是否包含某个元素
public boolean containsAll(Collection<?> collection);
是否包含某个集合
public boolean equals(Object object);
两个集合是否相等
public E get(int location);
根据位置获取元素
public int hashCode();
获取huhash码
public int indexOf(Object object);
查找某个元素的位置(第一次出现)
public boolean isEmpty();
是否为空集合
public Iterator<E> iterator();
迭代器
public int lastIndexOf(Object object);
元素最后一次出现的下标
public ListIterator<E> listIterator();
迭代器
public ListIterator<E> listIterator(int location);
public E remove(int location);
删除某个特定位置的元素
public boolean remove(Object object);
删除某个元素
public boolean removeAll(Collection<?> collection);
删除参数中的集合中的元素
public boolean retainAll(Collection<?> collection);
删除不属于参数中集合中的元素
public E set(int location, E object);
替代特定位置中的元素
public int size();
长度
public List<E> subList(int start, int end);
截取相应的集合
public Object[] toArray();
转换成数组
public <T> T[] toArray(T[] array);
放在指定数组,如果数组够大则装,不够大新建数组
Set也是一个接口,直接继承了Collection接口,Set的特点有:不允许有重复的元素,也就是说集合中任意两个元素,有e1.equals(e2)返回是false的,最多只有一个null元素,Set是无序的,意思是存进去的顺序和取出来的顺序基本不一致的。Set的具体实现有:HashSet,TreeSet等。Set的源码如下:
int size();
获取集合的元素总数量
boolean isEmpty();
是否是空集合,是的话则返回true
boolean contains(Object o);
判断集合是否包含该元素
Iterator<E> iterator();
迭代器
Object[] toArray();
转换为数组
boolean add(E e);
新增元素,如果返回true表示添加成功
boolean addAll(Collection<? extends E> c);
新增整个集合
boolean remove(Object o);
删除元素,true表示删除成功
boolean containsAll(Collection<?> c);
是否包含特定集合里的所有元素,
boolean removeAll(Collection<?> c);
删除整个集合中的元素
boolean retainAll(Collection<?> c);
包含该集合,这个方法应该是跟上面那个方法互斥,
void clear();
清空集合
boolean equals(Object o);
比较集合
int hashCode();
获取哈希码,这是set很重要的方法,
Map是一种键值对形式数据结构,形如Map《K,V》的形式,Map中一般来说Key是唯一的,不能重复,一个key也对应一个value,Map的key值是否是有序的要看具体实现,映射的value是否可以为空也看具体实现,Map的具体实现有:TreeMap,HashMap等。Map的源码如下:
int size();
返回集合的键值对数量
boolean isEmpty();
是否包含键值对
boolean containsKey(Object key);
是否包含key值
boolean containsValue(Object value);
是否包含value值
V get(Object key);
根据key值获取对应映射的value
V put(K key, V value);
添加一对键值对,如果key原本存在,则用新的value替代原有的value,返回的是原有的value
V remove(Object key);
根据key来删除键值对,如果返回value值存在代表删除成功
void putAll(Map<? extends K, ? extends V> m);
添加整个Map集合
void clear();
清空键值对
Set<K> keySet();
返回所有的key组成的Set集合 (从这里可以看出key是Set集合的形式,也就说说key是不允许重复的)
Collection<V> values();
返回所有的value组成的集合
Set<Map.Entry<K, V>> entrySet();
返回键值对的形式
boolean equals(Object o);
比较集合是否相同
int hashCode();
返回哈希码
分析了集合中三个重要的接口源码,List,Set和Map,可以看出集合无非也是对数据的增删改查操作。都有add(List和Set)或put(Map)来新增元素,remove来删除元素,contains来查询是否包含某个元素等。不过与数据持久化不一样,集合中增加或修改数据并不能永久保留,也只是停留在内存里,如果没有做数据持久化,比如保存在磁盘或者网络上,下次使用同一个集合,并没有数据,还需要重新初始化,然后进行增删改查等操作。
当然Java中具体集合是有很多的,以上三个接口只是代表了三种类型的集合,每种接口又有很多具体集合实现类,我们在具体应用中,应当根据应用的场景来选择不同的集合。至于每种集合的不同特点,在什么场景中选择什么集合,会在后面每个具体集合讲解中详细分析。