java集合框架
最早的版本java只是为最常用的数据结构提供一组类:
Vector、Stack、Hashtable、BitSet与Enumeration接口。其中Enumeration接口提供一种用于访问任意容器中各个元素的抽象机制。后续的版本中设计者对整个体系进行优化,希望将传统的类融入新的框架中,并使得整体类库规模小利于学习。
集合接口与实现分离
与现代数据结构类库的常见做法一样,java集合类库也将接口与实现分离。下面以队列为例:
队列接口指出可以在队列的尾部添加元素,在头部删除元素。并且可以查找队列中元素个数。
队列接口的最简形式大概如下:
public interface Queue<E>
//a simplified form of the interface in the standard library
{
void add(E element);
E remove();
int size();
}
队列的实现方法有循环数组和链表两种
下面是逻辑上的模仿,不与库中的实际代码完全相同
public class CircularArrayQueue<E> implements Queue<E>
{
private int head;
private int tail;
CircularArrayQueue(int capacity){...}
public void add(E element){...}
public E remove(){...}
public int size(){...}
private E[] elements;
}
public class LinkedListQueue<E> implements Queue<E>
{
private Link head;
private Link tail;
LinkedListQueue(){...}
public void add(E element){...}
public E remove(){...}
public int size(){...}
}
此时的构造就变成了:
Queue <Customer> expressLane = new CircularArrayQueue<>(100);
expressLane.add(new Customer("Harry"));
————————————————————————
Collection接口
在java类库中,集合类的基本接口是Collection接口,这个接口有两个基本方法:
public interface Collection<E>
{
boolean add(E element );
Iterator<E> iterator();
...
}
add用于向集合中添加元素。
iterator方法用于返回一个实现Iterator接口的对象。可以使用这个迭代器对象一次访问集合中的元素。
————————————————————————
迭代器
Iterator接口包含四个方法:
public interface Interator<E>
{
E next();
boolean hasNext();
void remove();
default void forEachRemaining(Consumer <? super E>action)
}
通过反复调用next方法可以遍历集合中所有元素。但是到了集合末尾的话,next方法将抛出一个NoSuchElementException。因此,需要在调用next之前调用hasNext方法。如果迭代器还有多个可以访问的元素则返回true。
请求一个迭代器后遍历集合:
Collection<String> c= ...;
Iterator<String> iter = c.iterator();
while (iter.hasNext())
{
String element = iter.next();
//do something with elements
}
用for each循环的相同操作:
for (String element:c)
{
//do something with element
}
for-each循环可以处理任何实现了Iterable接口的对象,这个接口只包含一个抽象方法:
public interface Iterable<E>
{
Iterator <E> iterator();
...
}
Collection接口扩展了Iterable接口。因此对标准类库中所有的集合都能应用 for-each循环。
也可以不用循环,使用forEachRemaining方法并提供一个lambda表达式。将对所有元素进行表达式中的处理
iterator.forEachRemaining(element ->
//do something with element
)
这种操作的顺序决定于集合类型:ArrayList,从0开始一个个迭代。Hashset中的元素则会按照一种基本上随机的顺序获得。
————————————————————————————
集合的next理解
有一种思路是讲Iterator.next与InputStream.read看做等效的。从数据流中读取一个字符,就会自动的"消耗掉"这个字节。下一次调用read将会消耗并返回输入的下一个字节。用同样的方式,反复的调用next就可以读取集合中的所有元素。
next将会返回此时越过的元素
- Iterator接口的remov方法将会删除上次调用next方法时返回的元素。
如下,删除一个字符串集合中第一个元素:
Iterator <String> it = c.iterator();
it.next();//skip over the first element
it.remove();//now remove it
- next()、remove()方法之间存在依赖性。如果在一个remove调用前没有调用next是不合法的。将会抛出一个IllegalStateException异常
如果想删除两个相邻的元素,不能直接这样调用:
it.remove();
it.remove();
实际上,必须用next先越过要删除的元素:
it.remove();
it.next();
it.remove();
泛型实用方法
由于Collection和Iterator都是泛型接口,这意味着可以编写处理任何集合类型的实用方法。例如,下面是一个检测任意集合是否包含指定元素的泛型方法:
public static <E> boolean contains(Collection<E> c,Object object)
{
for(E element: c)
if(element.equals(obj))
return true;
return false;
}
事实上,Collection接口声明了很多有用的方法,但是所有的类必须实现这些方法,这很实用但是也很累人。java类库中提供了一个实现Collection的类AbstractCollection,它保持基础方法size和Iterator仍为抽象方法,但是对例行的实用方法进行了实现,
p372中提供了这些方法的大概功能需求。
具体的实现集合还是看书吧2333.