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<E> 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<Map.Entry<K, V>>entrySet()
返回所有映射关系的集合;然后可以根据迭代器和映射关系对键值对操作。Collection<V>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<Integer,String> map = new HashMap<>();
// methods(map);
// keySetDemo(map);
entrySetDemo(map);
}
public static void methods(Map<Integer,String> 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<Integer,String> map) {
map.put(2, "Sam");
map.put(8, "Jane");
map.put(6, "Sun");
map.put(7, "Ben");
/**
* 取出map中的所有元素
* 原理:通过keySet方法获取map中所有键的集合Set,再通过Set的迭代器取到每一个键
* 通过每一个键可以获取其对应的值
*/
Set<Integer> keySet = map.keySet();
Iterator<Integer> 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<Integer,String> 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<Map.Entry<Integer,String>> entrySet = map.entrySet();
Iterator<Map.Entry<Integer,String>> iterator = entrySet.iterator();
while (iterator.hasNext()) {
Map.Entry<Integer,String> 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中的键排序;
- 不是同步的。