持有对象
上图为简化图(其中粗线部分是重点的容器),下图为完整容器分类图
点线框表示接口,实线框表示具体的类。
带有空心箭头的点线表示一个特定的类实现了一一个接口,实心箭头表示某个类可以生成箭头所指向的类的对象。
泛型和类型安全的容器
Java SE5之前的容器存在一个主要问题就是编译器允许你向容器中插入不正确的类型,例如向Apple对象的ArrayList容器中插入Orange对象,从而越界引发错误 。
通过使用泛型,就可以在编译期防止将错误类型的对象放置到容器中:
例如:ArrayList<Apple> a = new ArrayList<Apple>
当你指定了某个类型作为泛型参数时,你并不仅限于只能将该确切类型的对象放置到容器中,向上转型也可以作为其他类型一样作用于泛型。
基本概念
Java容器类库的用途是保存对象,并将其划分为两个不同的概念:
- Collection。一个独立元素的序列,这些元素都服从一条或多条规则。List必须按照插入的顺序保存元素,而Set不能有重复元素。Queue按照排队规则来确定对象产生的顺序(通常与他们被插入的顺序相同)。
- Map。一组成对的键值对对象,允许你通过键来查找值。ArrayList允许你使用数字来查找值,因此在某种意义上讲,它将数字与对象关联在了一起。映射表允许我们使用另一个对象来查找某个对象,它也被称为关联数组,或者字典。
添加一组元素
import java.util.*;
public class AddGroups {
public static void main(String[] args) {
Collection<Integer> collection = new ArrayList<Integer>(Arrays.asList(1,2,3,4,6));
Integer[] moreInts = {5,7,8,9,10};
System.out.println(collection);
collection.addAll(Arrays.asList(moreInts));
System.out.println(collection);
Collections.addAll(collection,11,12,13,14,15);
System.out.println(collection);
Collections.addAll(collection,moreInts);
System.out.println(collection);
List<Integer> list = Arrays.asList(16,17,18,19,20);
System.out.println(list);
list.set(1, 99);
System.out.println(list);
}
}
/*
[1, 2, 3, 4, 6]
[1, 2, 3, 4, 6, 5, 7, 8, 9, 10]
[1, 2, 3, 4, 6, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15]
[1, 2, 3, 4, 6, 5, 7, 8, 9, 10, 11, 12, 13, 14, 15, 5, 7, 8, 9, 10]
[16, 17, 18, 19, 20]
[16, 99, 18, 19, 20]
*/
容器的打印:
import java.util.*;
public class PrintContainers {
static Collection fill(Collection<String> collection) {
collection.add("rat");
collection.add("cat");
collection.add("cat");
return collection;
}
static Map fill(Map<String,String> map) {
map.put("rat", "Fuzzy");
map.put("cat", "Rags");
map.put("dog","Bosco");
return map;
}
public static void main(String[] args) {
System.out.println(fill(new ArrayList<String>()));
System.out.println(fill(new LinkedList<String>()));
System.out.println(fill(new HashSet<String>()));
System.out.println(fill(new TreeSet<String>()));
System.out.println(fill(new LinkedHashSet<String>()));
System.out.println(fill(new HashMap<String,String>()));
System.out.println(fill(new TreeMap<String,String>()));
System.out.println(fill(new LinkedHashMap<String,String>()));
}
}
/*
[rat, cat, cat]
[rat, cat, cat]
[rat, cat]
[cat, rat]
[rat, cat]
{rat=Fuzzy, cat=Rags, dog=Bosco}
{cat=Rags, dog=Bosco, rat=Fuzzy}
{rat=Fuzzy, cat=Rags, dog=Bosco}
*/
这里展示了Java容器的类库中的两种主要类型,它们的区别在于容器中每个“槽”保存的元素个数。Collection在每个槽中只能保存一个元素。此类容器包括:List,它以特定的顺序保存一组元素;Set,元素不能重复;Queue,只允许在容器的一“端”插入对象,并从另一“端”移除对象。Map在每个槽内保存了两个对象,即键和与之相关联的值。
默认的打印行为(容器提供的toString()方法)即可生成可读性很好的结果。
List
List承诺可以将元素维护在特定的序列中。List接口在Collection的基础上添加了大量的方法,使得可以在List的中间插入、移除元素,或者自我调整尺寸。
ArrayList:长于随机访问元素,但是在List的中间插入和移除元素时较慢。
LinkedList:通过代价较低的在List中间进行的插入和删除操作,提供了优化的顺序访问。LinkedList在随机访问方面相对比较慢,但是它的特性集较ArrayList更大。
- contains() 方法用来确定某个对象是否在列表中。
- remove() 移除一个对象。
- indexOf() 查找该对象在List中所处位置的索引编号。
- retainAll() 方法是一种有效的“交集”操作。
- removeAll() 移除List中所有的元素。
- . . . . . .
迭代器
迭代器也是一种设计模式。
Iterator
Java的Iterator只能单向移动,只能用来:
- 使用方法iterator() 要求容器返回一个Iterator.Iterator将准备好返回序列的第一个元素。
- 使用next() 获得序列中的下一个元素。
- 使用hasNext() 检查序列中是否还有元素。
- 使用remove() 将迭代器返回的元素删除。
import java.util.Iterator;
public class CrossConrtainerIteration{
public static void display(Iterator<Pet> it) {
while (it.hasNext()) {
Pet p = it.next();
System.out.print(p.id()+":"+p);
}
System.out.println();
}
}
ListIterator
ListIterator是一个更加强大的Iterator的子类型,它只能用于各种List的访问。
ListIterator可以双向移动,。它还可以产生相对于迭代器在列表中指向当前位置的前一个和后一个元素的索引。
LinkedList
LinkedList像ArrayList一样实现了基本的List接口,在执行List中间插入和移除比ArrayList更加高效,但是在随机访问方面较为逊色。
LinkedList还添加了可以使其作用于栈、队列或双端队列的方法。
Stack
“栈”通常是指“后进先出”(LIFO)的容器。有时栈也被称为叠加栈,因为最后“压入”栈的元素,第一个“弹出
”栈。
Set
Set不保存重复得元素。
import java.util.*;
public class SetOfInteger{
public static void main(String[] args) {
Random rand = new Random(47);
Set<Integer> intset = new HashSet<Integer>();
for (int i = 0; i < 1000; i++) {
intset.add(rand.nextInt(30));
}
System.out.println(intset);
}
}
/*
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
*/
Map
Queue
队列是典型的先进先出(FIFO)的容器。