一、Java集合框架
Java集合类库也将接口与实现分离。
队列接口指出可以在队列的尾部添加元素,在队列的头部删除元素,并且可以查找队列中元素的个数。
队列通常有两种实现方式:一种是使用循环数组;另一种是使用链表。
可以使用接口类型存放集合的引用。
循环数组要比链表更高效,但循环数组是一个有界集合,如果对象数量没有上限,最好使用链表来实现。
在Java类库中,集合类的基本接口是Collection接口,这个接口有两个基本方法:
public interface Collection<E> { boolean add(E element); Iterator<E> iterator(); .... }
add方法用于向集合中添加元素。如果添加元素确实改变了集合就返回true,如果集合没有发生变化就返回false。
Iterator方法用于返回一个实现了Iterator接口的对象。可以使用这个迭代器对象依次访问集合中的元素。
Iterator接口中包含四个方法:
public interface Iterator { E next(); boolean hasNext(); void remove(); default void forEachRemaining(Consumer<? super E> action); }
通过反复调用next方法,可以逐个访问集合中的每个元素。但是,如果到达了集合的末尾,next方法将会抛出一个NoSuchElementException。因此,需要在调用next之前调用hasNext方法,如果迭代器对象还有多个供访问的元素,这个方法就会返回true。
编译器简单的将“for each”循环编译为带有迭代器的循环。
Collection接口扩展了Iterable接口,因此,对于标准类库中的任何集合都可以使用“for each”循环。
在Java SE8中,可以调用forEachRemaining方法并提供一个lambda表达式,将对迭代器的每一个元素调用这个lambda表达式,直到再没有元素为止。
Java迭代器应该被认为是位于两个元素之间。当调用next时,迭代器就越过下一个元素,并返回刚刚越过的那个元素的引用。
Iterator接口的remove方法将会删除上次调用next方法时返回的元素,如果想要删除指定位置上的元素,仍然需要越过这个元素。
对next方法和remove方法的调用具有互相依赖性,如果调用remove之前没有调用next将是不合法的,会抛出一个IllegalStateException异常。
集合框架的接口:
集合有两个基本接口:Collection和Map。
List是一个有序集合。元素会增加到容器中的特定位置。可以采用两种方式访问元素:用迭代器访问;是用一个整数索引来访问。后一种方法称为随机访问,因为这样可以按任意顺序访问元素。与之不同,使用迭代器访问时,必须顺序的访问元素。
集(Set)的add方法不允许增加重复的元素。要适当的定义集的equals方法:只要两个集包含同样的元素就认为是相等的,而不要求这些元素有相同的顺序。hashCode方法的定义要保证包含相同元素的两个集会得到相同的散列码。
二、具体的集合
在Java程序设计语言中,所有链表实际上都是双向链接的——即每个结点还存放着指向前驱结点的引用。
链表是一个有序集合。
add方法只依赖于迭代器的位置,而remove方法依赖于迭代器的状态。
可以根据需要给容器增加很多个迭代器,但是这些迭代器只能读取列表,另外,再单独增加一个既能读,又能写的迭代器。
使用链表的唯一理由是尽可能减少在列表中间插入或删除元素所付出的代价。
散列表是一种可以快速查找到所需要对象的数据结构。散列表为每个对象计算一个整数,称为散列码。
树集是一个有序集合,要使用树集,必须能够比较元素,这些元素必须实现Comparable接口,或者构造集时必须提供一个Comparator。
树的排序必须是全序,任意两个元素必须是可比的,并且只有在两个元素相等时结果才为0。
有两个端头的队列,即双端队列,可以让人们有效的在头部和尾部同时添加和删除元素。
优先级队列中的元素可以按照任意的顺序插入,却总是按照顺序的顺序进行检索。
三、映射
Java类库为映射提供了两个通用的实现:HashMap和TreeMap。
散列映射对键进行散列,树映射用键的整体顺序对元素进行排序,并将其组织成搜索树。
四、遗留的集合
1、HashTable类
2、枚举(Enumeration)
3、属性映射(Properties):有三个特性:
A、键与值都是字符串。
B、表可以保存到一个文件中,也可以从文件中加载。
C、使用一个默认的辅助表。
4、栈(Stack)
5、位集(BitSet)