原文: oodesign
诱因
集合 是 软件开发中最常用的一种数据结构。用于存储一类对象。
既然保存了对象,那么就必须提供获取对象的方法,这些方法还不能暴露其内部的结构。
迭代器模式(Iterator Pattern)的思想是由迭代器 负责 集合中对象的 获取 和 迭代,将集合放入 迭代器对象中,迭代器对象会持有 集合的当前循环状态,时刻跟踪 当前的对象,并且可以确定下一个 要被迭代的对象。
思路
提供一个不暴露底层实现 就可以访问 到一个聚合对象元素的方法;
迭代器模式 提供的抽象 允许你 不用在集合之外进行任何的更改 就可以 修改集合的实现。
实现
UML 图
成员:
Aggregate:提供获取 Iterator 迭代器的方法,一般是一个需要迭代的容器抽象;例如 Java api 中的 Iterable接口, Collection 接口;List 接口,Set 接口;
ConcreteAggregate:Aggregate 实现类 ,例如 jdk 中的 ArrayList,内部容器为数组
Iterator:定义迭代元素所需要的方法 ,例如 jdk 中的 Iterator ,ListIterator;
ConcreteIterator: 具体实现,例如 jdk 中 ArrayList 的内部类 Itr (Iterator 实现类),ListItr(ListIterator 实现类);
案例 1:不使用 jdk 提供的 集合,自定义集合迭代
相关类:
IContainer : 集合容器接口;
BooksCollection :容器实现类,
BookIterator : BooksCollection 内部类, Iterator 实现类
IIterator : 迭代器 接口
Main : 测试入口
相关代码:
IContainer:
package com.ycit.iterator;
/**
* Created by xlch on 2017/3/23.
*/
public interface IContainer {
IIterator createIterator();
}
IIterator:
package com.ycit.iterator;
/**
* Created by xlch on 2017/3/23.
*/
public interface IIterator {
boolean hasNext();
Object next();
}
BooksCollection 及其内部类 BookIterator
package com.ycit.iterator;
/**
* Created by xlch on 2017/3/23.
*/
public class BooksCollection implements IContainer {
private String books [] = {"think in java","head first design pattern","ElasticSearch cookbook"};
@Override
public IIterator createIterator() {
return new BookIterator();
}
private class BookIterator implements IIterator {
private int pos;
@Override
public boolean hasNext() {
if (pos < books.length) {
return true;
}else {
return false;
}
}
@Override
public Object next() {
if (hasNext()) {
return books[pos++];
}else {
return null;
}
}
}
}
Main:
package com.ycit.iterator;
/**
* Created by xlch on 2017/3/27.
*/
public class Main {
public static void main(String [] args) {
BooksCollection booksCollection = new BooksCollection();
IIterator it = booksCollection.createIterator();
while (it.hasNext()) {
System.out.println(it.next());
}
}
}
输出结果:
think in java
head first design pattern
ElasticSearch cookbook
案例2:分析 jdk 中的 集合
jdk 中的集合 类图 (摘自 那些年的事儿 ,表示感谢,另外1.6之后 TreeSet 直接父类为 NavigableSet ,间接父类为 SortedSet ):
顶层父类:
Collection : 继承了 Iterable 接口 ,
Iterable : 实现该接口的对象可以使用 "foreach" 语句;
参数 : Iterator ,集合的迭代器,代替了 Java 集合框架中的 Enumeration ,提供了以下抽象方法:
boolean hasNext();
E next();
void remove();
首先看 List 接口下的集合实现类 :
List : 有序的集合 ,允许重复元素
实现类:
ArrayList : 大小可调整的数组的实现 ,内部容器为数组,默认容量 10; Itr 为 Iterator 在 ArrayList 中的内部实现类;
LinkedList : 双(向)链表(Doubly-linked list)的实现 ,双向链表 是一种 由 一组称为节点(node)的顺序链接记录组成的 链接数据结构。每个节点包含两个字段,称为链接(links),这两个链接分别指向该节点的 前一个节点 和 后一个节点 的引用;
Java 中 LinkedList 部分源码(JDK1.8.0_101):
public class LinkedList<E>
extends AbstractSequentialList<E>
implements List<E>, Deque<E>, Cloneable, java.io.Serializable
{
// ...
// 添加元素
public boolean add(E e) {
linkLast(e);
return true;
}
// 添加元素的真正逻辑:
void linkLast(E e) {
final Node<E> l = last;//取出列表中最后一个节点
final Node<E> newNode = new Node<>(l, e, null); //创建新添加元素的节点
last = newNode;//新添加的节点成为新的最后一个节点
if (l == null) //如果当前列表不存在最后一个节点,即列表为空
first = newNode;
else
l.next = newNode;
size++;
modCount++;
}
// 节点类,三部分组成:值;前一个节点;后一个几点
private static class Node<E> {
E item;
Node<E> next;
Node<E> prev;
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
Set 接口下的实现类 :
Set :不允许重复元素的集合
子类:
HashSet : 哈希表的实现,内部容器为 HashMap,默认初始容量为 16 ;不能保证集合迭代的顺序,即无序 ;非同步
子类:
LinkedHashSet:哈希表 和 链接列表的实现,可以预见集合迭代的顺序,即有序;
SortedSet :
子类:
TreeSet:基于 TreeMap 的 NavigableSet 的实现;可以自定义排序规则;
,