前言:Java最初版本只为最常用的数据结构提供了很少的一组类:Vector、Stack、Hashtable、BitSet和Enumeration接口。其中,Enumeration接口提供了一种用于访问任意容器中各个元素的抽象机制。与现代数据结构类库常见情况一样,Java集合类库将接口(interface)和实现(implementation)分离。
1、队列(Queue)接口:
1.1、规则:可以在队列末尾添加元素,在队列头部删除元素,查找队列中元素的个数。遵循“先进先出”的规则。
1.2、实现方式:使用循环数组(例如ArrayDeque),或者使用链表(例如LinkedList)。循环数组的效率比链表高,但是循环数组是一个有界集合,因此容量有限。如果程序需要的对象数量没有上限,最好考虑使用链表。
1.3、Abstract类的API:API文档中有一组名字以Abstract开头的类,是为类库实现者设计的,如有需要,扩展这些类比实现Queue接口中的所有方法方便得多。
2、Collection接口:Java类库中集合类的基本接口。
2.1、两个基本方法:Collection接口有很多方法,其中:
(1)add(E e)方法向集合添加元素。如果添加元素确实改变了集合则返回true,如果集合没有变化则返回false。
(2)iterator()方法返回一个实现了Iterator接口的迭代器对象,可以用来依次访问集合中的元素。
3、迭代器(Iterator):Iterator接口包含4个方法,其中:
(1)next()方法:通过反复调用,可以逐个访问集合中的元素。但如果达到集合的末尾,此方法会抛出NoSuchElementException。因此,需要先用hasNext()方法判断是否还有下一个元素。
(2)hasNext()方法:如果迭代器还有供访问的元素返回true,否则返回false。调用next()方法之前需先通过此方法判断。
Collection c = new ArrayList<>();
Iterator iterator = c.iterator();
while (iterator.hasNext()){
String s = iterator.next();
System.out.print(s);
}
(3)可以使用“for each”循环更加简练地表示同样的循环操作:
Collection c = new ArrayList<>();
for (String str : c) {
System.out.print(s);
}
Java SE 8中,还可以使用 forEachRemaining方法并提供一个lambda表达式。
Collection c = new ArrayList<>();
c.iterator().forEachRemaining(e->{
System.out.print(e);
});
(4)remove()方法:删除上一次调用next()方法时返回的元素。对next方法和remove方法的调用具有互相依赖性,如果调用remove之前没有调用next,将会抛出一个IllegalStateException。
(5)区别:Java集合类库的迭代器与其他类库的迭代器在概念上有所区别。传统集合类库,诸如C++标准模板库,迭代器是根据数组索引建模的,给定一个这样的迭代器就可查看指定位置上的元素,如同知道数组索引i就可以查看数组元素a[i]。而Java迭代器却是查找操作与位置变更紧密相连,查找元素的唯一方法是调用next方法,而迭代器会越过下一个元素,并返回越过的那个元素的引用。
(6)元素访问顺序:集合类型不同会影响元素访问的顺序。例如,ArrayList迭代器从索引0开始,每迭代一次索引值加1。而HashSet元素出现的顺序是随机的。
4、集合框架中的接口:集合有两个基本接口:Collection和Map
4.1、List接口:
(1)List是一个有序集合(ordered collection),元素会添加到容器中的特定位置。可以采用两种方式访问元素:迭代器访问,或者随机访问(random access,即使用一个整数索引来访问)。
(2)实际上,有两种有序集合,性能开销有很大差异。一种是由数组支持的有序集合,可以快速地随机访问,适合使用List方法并提供一个整数索引来访问;一种是链表,随机访问很慢,最后使用迭代器来遍历。
(3)集(set):集的add方法不允许增加重复的元素,要适当地定义集的equals方法:只要两个集包含同样的元素(不管元素顺序),就认为是相等的。hashCode方法的定义要保证包含相同元素的两个集会得到相同的散列码。