java核心技术卷I-集合框架

Java集合框架

与现代的数据结构类库的常见情况一样, Java 集合类库也将接口(interface) 与 实 现(implementation) 分离

队列 (queue)

队列接口指出可以在队列的尾部添加元素, 在队列的头部删除元素,并且可以查找队列中元素的个数。当需要收集对象, 并按照“ 先进先出” 的规则检索对象时就应该使用队列

public interface Queue<E> // a simplified form of the interface in the standard library
{
	void add(E element);
	E remove();
	int size();
}

这个接口并没有说明队列是如何实现的。队列通常有两种实现方式: 一种是使用循环数组;另一种是使用链表。

Collection接口

在 Java 类库中,集合类的基本接口是 Collection 接口。这个接口有两个基本方法

public interface Collection<E>
{
	boolean add(E element);
	Iterator<E> iterator();
...
}

add方法用于向集合中添加元素。如果添加元素确实改变了集合就返回 true, 如果集合没有发生变化就返回 false。
iterator方法用于返回一个实现了 Iterator 接口的对象。可以使用这个迭代器对象依次访问集合中的元素。

迭代器

Iterator接口包含4个方法:

public interface Iterator<E>
{
	E next();
	boolean hasNext();
	void remove();
	default void forEachRemaining(Consumer<? super E> action);
}

通过反复调用 next 方法,可以逐个访问集合中的每个元素。但是,如果到达了集合的末尾,next 方法将抛出一个 NoSuchElementException。 因此,需要在调用 next 之前调用 hasNext方法。如果迭代器对象还有多个供访问的元素, 这个方法就返回 true。如果想要查看集合中的所有元素,就请求一个迭代器,并在 hasNext 返回 true 时反复地调用 next 方法。

Collection<String> c = . . .;
Iterator<String> iter = c.iterator();
while (iter.hasNext())
{
	String element = iter.next();
	//do something with element
}

用“ for each” 循环可以更加简练地表示同样的循环操作:
for (String element : c)
{
//do something with element
}
Collection接口扩展了 Iterable 接口。因此,对于标准类库中的任何集合都可以使用“ for
each” 循环。
在 Java SE 8中,甚至不用写循环。可以调用 forEachRemaining 方法并提供一 lambda表达式(它会处理一个元素)。 将对迭代器的每一个元素调用这个 lambda 表达式,直到再没有元素为止。
元素被访问的顺序取决于集合类型。 如果对 ArrayList 进行迭代, 迭代器将从索引 0开始,每迭代一次,索引值加 U 然而,如果访问 HashSet 中的元素, 每个元素将会按照某种随机的次序出现。虽然可以确定在迭代过程中能够遍历到集合中的所有元素,但却无法预知元素被访问的次序。这对于计算总和或统计符合某个条件的元素个数这类与顺序无关的操作来说,并不是什么问题。
Java 迭代器查找操作与位置变更是紧密相连的。查找一个元素的唯一方法是调用 next, 而在执行查找操作的同时, 迭代器的位置随之向前移动,应该将 Java 迭代器认为是位于两个元素之间。 当调用 next 时,迭代器就越过下一个元素,并返回刚刚越过的那个元素的引用。
Iterator 接口的 remove 方法将会删除上次调用 next 方法时返回的元素。

it.next(); // skip over the first element
it. remove(); // now remove it

集合框架中的接口

集合有两个基本接口:Collection 和 Map。 我们已经看到,可以用以下方法在集合中插人元素:

boolean add(E element)

不过,由于映射包含键 / 值对,所以要用 put 方法来插人:

V put(K key, V value)

要从集合读取元素, 可以用迭代器访问元素。不过,从映射中读取值则要使用 get 方法:

V get(K key)

List

List 是一个有序集合。元素会增加到容器中的特定位置。可以采用两种方式访问元素:使用迭代器访问, 或者使用一个整数索引来访问。后一种方法称为随机访问(random access ), 因为这样可以按任意顺序访问元素。与之不同, 使用迭代器访问时,必须顺序地访问元素
List 接口定义了多个用于随机访问的方法:

void add(int index, E element)
void remove(int index)
E get(int index)
E set(int index, E element)

坦率地讲,集合框架的这个方面设计得很不好。实际中有两种有序集合,其性能开销有
很大差异。由数组支持的有序集合(ArrayList)可以快速地随机访问,因此适合使用 List 方法并提供一个整数索引来访问。与之不同, 链表(LinkedList)尽管也是有序的, 但是随机访问很慢,所以最好使用迭代器来遍历。如果原先提供两个接口就会容易一些了。

Set

Set 接口等同于 Collection 接口,不过其方法的行为有更严谨的定义。集(set) 的 add方法不允许增加重复的元素。要适当地定义集的 equals 方法:只要两个集包含同样的元素就认为是相等的,而不要求这些元素有同样的顺序。hashCode 方法的定义要保证包含相同元素的两个集会得到相同的散列码。
SortedSet 和 SortedMap 接口会提供用于排序的比较器对象,这两个接口定义了可以得到集合子集视图的方法。
最后,Java SE 6 引人了接口 NavigableSet 和 NavigableMap, 其中包含一些用于搜索和遍历有序集和映射的方法。(理想情况下,这些方法本应当直接包含在 SortedSet 和 SortedMap接口中)。TreeSet 和 TreeMap 类实现了这些接口。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章