I. 完整的容器分类法
上图不包括Queue的内容,部分Map实现类未给出。
II. 容器各层次常用方法
数组是保存一组对象的最有效的方式,如果要保存一组基本类型数据,也推荐使用这种方式(数组既可以存储基本类数据也可以存储引用类型数据)。但是数组具有固定尺寸,而在更一般的情况中,程序并不知道将需要多少个对象,或者是否需要更复杂的方式来存储对象,因此数组尺寸固定这一限制显得过于受限了。
Java 提供了一套相当完整的容器类来解决这个问题,其中基本类型是 List、Set 、Queue和Map。 这些对象类型也称为集合类,但由于Java的类库中使用了Collection这个名字来指代该类库的一个特殊子集,所以我们使用范围更广的术语容器(Container)来称呼它们。
1. Collection
Collection 是容器的一个根接口。封装了Collection子接口(类)的共性方法。其常用方法有:
- 添加类方法
- boolean add(E e)
向集合中添加一个元素;添加成功为true,添加失败为false。 - boolean addAll(Collection extends E> c)
将指定collection中的所有元素都添加到此collection中;添加成功为true,添加失败为false。
- boolean add(E e)
- 删除类方法
- boolean remove(Object o)
删除集合中指定对象;删除成功为true,删除失败为false。 - boolean removeAll(Collection> c)
移除此collection中那些也在指定collection中的所有元素。 - void clear()
移除此 collection 中的所有元素。
- boolean remove(Object o)
- 判断类方法
- boolean contains(Object o)
判断该集合是否包含指定元素;包含为true,不包含为false。 - boolean containsAll(Collection> c)
判断此collection是否包含指定collection中的所有元素;包含返回true,不包含返回 false。 - boolean isEmpty()
判断此collection是否为空;为空返回true,不为空返回false。
- boolean contains(Object o)
- 获取类方法
- int size()
返回此collection中元素个数。 - iterator iterator()
返回此collection的元素上进行迭代的迭代器(获取collection元素的一种方法)。
- int size()
- 其它类
- boolean retainAll(Collection> c)
仅保留此collection中也包含在指定collection中的元素(取交集);成功返回true。 - Object[] toArray()
返回此collection中所有元素的数组。
- boolean retainAll(Collection> c)
collection中的方法演示:
import java.util.ArrayList;
import java.util.Collection;
/**
* @Author: 落脚丶
* @Date: 2017/10/16
* @Time: 上午9:38
* @ClassName: CollectionDemo
* @Description: 演示collection接口中的方法。
*/
public class CollectionDemo {
public static void main(String[] args) {
Collection collection = new ArrayList();
Collection collection1 = new ArrayList();
Collection collection2 = new ArrayList();
show(collection);
show(collection1,collection2);
}
public static void show(Collection collection){
// 1. 添加元素。add
collection.add("abc1");
collection.add("abc2");
collection.add("abc3");
System.out.println(collection);// 集合直接打印以字符串输出
/**
* 输出结果:[abc1, abc2, abc3]
*/
// 2. 删除元素。remove
collection.remove("abc2"); // 会改变集合长度
System.out.println(collection);// 集合直接打印以字符串输出
/**
* 输出结果:[abc1, abc2, abc3]
*/
// 清空
// collection.clear();
// System.out.println(collection);// 集合直接打印以字符串输出
/**
* 输出结果:[]
*/
// 3. 包含
System.out.println(collection.contains("abc3"));
System.out.println(collection.contains("abc4"));
/**
* 输出结果:true false
*/
}
public static void show(Collection collection1, Collection collection2){
// 给collection1添加元素
collection1.add("abc1");
collection1.add("abc2");
collection1.add("abc3");
collection1.add("abc4");
// 给collection2添加元素
collection2.add("abc2");
collection2.add("abc6");
collection2.add("abc7");
System.out.println("collection1:" + collection1);
System.out.println("collection2:" + collection2);
/**
* Output:
* collection1:[abc1, abc2, abc3, abc4]
* collection2:[abc2, abc6, abc7]
*/
// 演示addAll
collection1.addAll(collection2); // 将collection2元素添加collection1中。
System.out.println("collection1:" + collection1);
/**
* Output:
* collection1:[abc1, abc2, abc3, abc4, abc2, abc6, abc7]
*/
// 演示removeAll
boolean b = collection1.removeAll(collection2);
// 将两个collection中相同元素从collection1中删除
System.out.println("removeAll:" + b);
System.out.println("collection1:" + collection1);
/**
* Output:
* removeAll:true
* collection1:[abc1, abc3, abc4]
*/
// 演示retainAll
boolean b = collection1.retainAll(collection2);
// 将两个collection中不相同元素从collection1中删除
System.out.println("retainAll:" + b);
System.out.println("collection1:" + collection1);
/**
* Output:
* retainAll:true
* collection1:[abc2]
*/
}
}
collection迭代器演示:
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
/**
* @Author: 落脚丶
* @Date: 2017/10/16
* @Time: 上午10:15
* @ClassName: IteratorDemo
* @Description: 迭代器演示
*/
public class IteratorDemo {
public static void main(String[] args){
Collection collection = new ArrayList();
collection.add("abc1");
collection.add("abc2");
collection.add("abc3");
collection.add("abc4");
// 使用Collection中的iterator()方法。调用集合迭代器方法,
是为了获取集合中迭代器对象。
Iterator iterator = collection.iterator();
while (iterator.hasNext()) { // while循环后iterator对象依然存在
System.out.println(iterator.next());
}
/**
* Output:
* abc1
* abc2
* abc3
* abc4
*/
for (Iterator iterator = collection.iterator(); iterator.hasNext(); ){
System.out.println(iterator.next());
}
// for循环结束后iterator会被释放
}
}
1.1 List
List特点:
- 有序(存入和取出顺序一致);
- 元素都有索引(下标);
- 元素可以重复。
List特有的常见方法:有一个共同特点是可以操作下标。
-
添加类方法
- void add(int index, E element)
在列表指定位置插入元素。 - boolean addAll(int index, Collection extends E> c)
将指定 collection 中的所有元素插入列表制定位置。
- void add(int index, E element)
-
删除类方法
- Object remove(int index)
移除指定下标的元素并返回。
- Object remove(int index)
-
修改类方法
- Object set(int index, E element)
修改指定下标的元素并返回修改之前的元素。
- Object set(int index, E element)
-
获取类方法
Object get(int index)
获取指定下标的元素。int indexOf(Object o)
返回第一次出现制定元素的索引;如果没有返回-1。int lastIndexOf(Object o)
返回最后出现制定元素的索引;如果没有返回-1。List subList(int fromIndex, int toIndex)
返回列表中指定的 fromIndex(包括)和 toIndex(不包括)之间的部分视图。
1.1.1 Vector
JDK1.0的时候只有Vector,JDK1.2以后才有 List。
内部是数组数据结构,长度可变(默认长度为 10,百分之百延长),是同步的(同步会降低速度)。
可变长度的实现是重新创建新的数组。
Vector常见特有的方法:
void addElement(Object o)
添加元素。int capacity()
返回当前容量。Object elementAt(int index)
根据索引查找元素。Object firstElement()
返回第一个元素。Object lastElement()
返回最后一个元素。void removeAllElements()
移除全部元素。void setElementAt(Object o, int index)
修改元素,与 set() 方法参数的顺序不同。Enumeration
elements()
返回组件的枚举(类似于迭代器,迭代器可以替代它)。
1.1.2 ArrayList
内部是数组数据结构,长度可变(百分之五十延长),是不同步的。替代了 Vector。查询元素的速度很快。
1.1.3 LinkedList
内部是链表数据结构,是不同步的。增删元素的速度很快。
LinkedList 特有的方法:
void addFirst(Object o)
在列表头添加元素。void addLast(Object o)
在列表尾部添加元素。Object getFirst()
返回列表第一个元素但不删除。Object getLast()
返回列表最后一个元素但不删除。Object removeFirst()
移除并返回列表第一个元素。Object removeLast()
移除并返回列表最后一个元素。
此处方法未全部列举。链表对头和尾的操作最明显。
1.2 Set
Set特点:
- 元素不能重复序;
- Set 接口中的方法与Collection一致。
1.2.1 HashSet
- 内部数据结构是哈希表,不同步。不保证迭代顺序(存取的顺序不一致)。
- 我们知道Hashtable的存储是基于散列(hashcode)的,其存储的位置和放入的顺序没有直接关系。所以从HashSet中取出的元素的顺序是未知的。
- HashSet如何保证元素的唯一性呢?
是通过对象的 hashCode 和 equals 方法来完成对象唯一性的。- 如果对象的hashCode值不同,那么不用判断equals方法,直接存储;
- 如果对象的hashCode值相同,那么要再次判断对象的 equals方法是否为true。如果为true则视为相同元素,不存。如果为false,那么视为不同元素,进行储存。
- 自定义类存储到 HashSet 中,通常要重写hashCode和equals方法。
- HashSet的子类LinkedHashSet
具有可预知迭代顺序的Set接口的哈希表和链表实现。此实现与HashSet的不同之外在于,后者维护着一个运行于所有条目的双重链表。此链表定义了迭代顺序,即按照将元素插入到Set中的顺序(插入顺序)进行迭代。
1.2.2 TreeSet
- 不同步;
- 使用元素的自然顺序对其排序;
- 放入其中的元素必须是可以比较的;
- 判断元素唯一的方式:根据比较方法的返回结果,返回0就表明元素相等,就不会存入。
2. Map
Map特点:
- Map一次存入一对元素(双列集合);
- Collection一次存入一个元素(单列元素);
- 必须保证键的唯一性。
Map常用方法:
-
添加类
- V put(K key, V value)
存入(修改)元素。若键存在,则返回键所对的值;否则返回 null。
- V put(K key, V value)
-
删除类
void clear()
清空集合。V remove(K key)
根据键移除该键值对,并返回值。
-
判断类
boolean containsKey(K key)
判断是否包含键。boolean containsValues(V value)
判断是否包含值。boolean isEmpty()
判断是否为空。
-
获取类
V get(K key)
通过键获取值,没有该键返回null。当然可以通过返回值来判断是否有该键。int size()
返回键值对个数。Set keySet()
返回所有键的集合;然后可以根据迭代器取所有值。Set
>entrySet()
返回所有映射关系的集合;然后可以根据迭代器和映射关系对键值对操作。Collection
values()
返回此映射中包含值的Collection视图。
Map常用方法演示:
import java.util.*;
/**
* @Author: 落脚丶
* @Date: 2017/11/8
* @Time: 下午6:57
* @Description: Map方法演示
*/
public class MapDemo {
public static void main(String[] args) {
Map map = new HashMap<>();
// methods(map);
// keySetDemo(map);
entrySetDemo(map);
}
public static void methods(Map map) { // 学号和姓名
// 添加元素
System.out.println(map.put(8, "wang"));
System.out.println(map.put(8, "li"));
map.put(2, "Sam");
map.put(7, "Jean");
System.out.println(map);
/**
* Output:
* null
* wang
* {2=Sam, 7=Jean, 8=li}
*/
// 删除
System.out.println("remove:" + map.remove(2));
System.out.println(map);
/**
* Output:
* remove:Sam
* {7=Jean, 8=li}
*/
// 获取
System.out.println("get:" + map.get(6));
System.out.println("get:" + map.get(8));
/**
* Output:
* get:null
* get:li
*/
}
/**
* @Date: 2017/11/8
* @Time: 下午7:18
* @Method: keySetDemo
* @Description: 演示keySet()方法
*/
public static void keySetDemo(Map map) {
map.put(2, "Sam");
map.put(8, "Jane");
map.put(6, "Sun");
map.put(7, "Ben");
/**
* 取出map中的所有元素
* 原理:通过keySet方法获取map中所有键的集合Set,再通过Set的迭代器取到每一个键
* 通过每一个键可以获取其对应的值
*/
Set keySet = map.keySet();
Iterator iterator = keySet.iterator();
while (iterator.hasNext()) {
Integer key = iterator.next();
String value = map.get(key);
System.out.println(key + ":" + value);
/**
* 2:Sam
* 6:Sun
* 7:Ben
* 8:Jane
*/
}
}
/**
* @Date: 2017/11/8
* @Time: 下午7:29
* @Method: entrySetDemo()
* @Description: 演示entrySet()方法
*/
public static void entrySetDemo(Map map) {
map.put(2, "Sam");
map.put(8, "Jane");
map.put(6, "Sun");
map.put(7, "Ben");
/**
* 通过Map转成Set就可以迭代
* 使用方法entrySet()
* 该方法返回映射关系对象到Set中,这个映射关系的类型就是Map.Entry类型
* 通过Map.Entry中的getKey()、getValue()方法获取键和值
*/
Set> entrySet = map.entrySet();
Iterator> iterator = entrySet.iterator();
while (iterator.hasNext()) {
Map.Entry me = iterator.next();
Integer key = me.getKey();
String value = me.getValue();
System.out.println(key + ":" + value);
/**
* 2:Sam
* 6:Sun
* 7:Ben
* 8:Jane
*/
}
}
}
2.1 Hashtable
- 内部结构是哈希表;
- 不允许 null 作为键、值;
- 是同步的。
2.2 HashMap
- 内部结构是哈希表;
- 允许 null 作为键、值;
- 不是同步的。
2.3 TreeMap
- 内部结构是二叉树;
- 可对Map中的键排序;
- 不是同步的。