声明:文章内容根据大牛博客的内容,自己理解后,给自己做的学习笔记,文末会附上大牛博客地址链接。有需要沟通交流的可加我QQ群:425120333
在项目开发中经常会使用到各种各样的容器,内部实现分为三种情况,分别是数组(ArrayList)、链表(LinkedList)、散列(Set),使用了容器就需要知道每个容器中包含的内容,
这时遍历整个容器就显得尤为重要。因为list是可以通过下标来访问的,存放的数据是有序的,这样的话通过序号遍历是能实现的,但是对set来说,是没法做到的,因为set是通过散列来存储数据的,
没有下标的说法,这样一来就没法通过下标访问。
下面参考jdk源码(主要是大牛的博客)自己分别实现ArrayList、LinkedList、Set三个类(简单实现)。
public class ArrayList<E> {
private static final Integer originSize = 10;
@SuppressWarnings("unchecked")
E[] array = (E[]) new Object[originSize];
private int size;
public void add(E e) {
if (size < originSize) {
array[size++] = e;
} else {
@SuppressWarnings("unchecked")
E[] copyArray = (E[]) new Object[10 + originSize];
System.arraycopy(array, 0, copyArray, 0, size);
copyArray[size++] = e;
array = copyArray;
}
}
public Object[] toArray() {
@SuppressWarnings("unchecked")
E[] copyArray = (E[]) new Object[size];
System.arraycopy(array, 0, copyArray, 0, size);
return copyArray;
}
public int size() {
return size;
}
}
public class LinkedList<E> {
private Entry<E> header = new Entry<E>(null, null, null);
private int size;
public LinkedList() {
header.next = header.previous = header;
}
public void add(E e) {
Entry<E> newEntry = new Entry<E>(e, header, header.next);
newEntry.previous.next = newEntry;
newEntry.next.previous = newEntry;
size++;
}
public Object[] toArray() {
Object[] array = new Object[size];
int i = size - 1;
for (Entry<E> e = header.next; e != header; e = e.next) {
array[i--] = e;
}
return array;
}
public int size() {
return size;
}
private class Entry<E> {
E value;
Entry<E> previous;
Entry<E> next;
public Entry(E value, Entry<E> previous, Entry<E> next) {
super();
this.value = value;
this.previous = previous;
this.next = next;
}
}
}
import java.util.HashMap;
import java.util.Map;
public class Set<E> {
private final static Object NULL = new Object();
private Map<E, Object> map = new HashMap<E, Object>();
public void add(E e) {
map.put(e, NULL);
}
public int size() {
return map.size();
}
public Object[] toArray() {
return map.keySet().toArray();
}
}
因为着三个类都是自己编写的,没有实现迭代器接口,没法用foreach来迭代遍历,这里编写自己的迭代其实现类(基本和jdk源码类似,简化了一些)。
public interface Iterator<E> {
public boolean hasNext();
public E next();
}
public interface Iterable<E> {
public Iterator<E> iterator();
}
接下来要修改原先的ArrayList和LinkedList实现迭代器接口
实现了迭代器的ArrayList:
package com.cmcc.review;
public class ArrayList<E> implements Iterable<E> {
private static final Integer originSize = 10;
@SuppressWarnings("unchecked")
E[] array = (E[]) new Object[originSize];
private int size;
public void add(E e) {
if (size < originSize) {
array[size++] = e;
} else {
@SuppressWarnings("unchecked")
E[] copyArray = (E[]) new Object[10 + originSize];
System.arraycopy(array, 0, copyArray, 0, size);
copyArray[size++] = e;
array = copyArray;
}
}
public Object[] toArray() {
@SuppressWarnings("unchecked")
E[] copyArray = (E[]) new Object[size];
System.arraycopy(array, 0, copyArray, 0, size);
return copyArray;
}
public int size() {
return size;
}
@Override
public Iterator<E> iterator() {
return new ListIterator();
}
private class ListIterator implements Iterator<E> {
int index = 0;
@Override
public boolean hasNext() {
if (index < size) {
return true;
}
return false;
}
@Override
public E next() {
return array[index++];
}
}
}
实现了迭代器的LinkedList:
package com.cmcc.review;
public class LinkedList<E> implements Iterable<E> {
private Entry<E> header = new Entry<E>(null, null, null);
private int size;
public LinkedList() {
header.next = header.previous = header;
}
public void add(E e) {
Entry<E> newEntry = new Entry<E>(e, header, header.next);
newEntry.previous.next = newEntry;
newEntry.next.previous = newEntry;
size++;
}
public Object[] toArray() {
Object[] array = new Object[size];
int i = size - 1;
for (Entry<E> e = header.next; e != header; e = e.next) {
array[i--] = e;
}
return array;
}
public int size() {
return size;
}
private class Entry<E> {
E value;
Entry<E> previous;
Entry<E> next;
public Entry(E value, Entry<E> previous, Entry<E> next) {
super();
this.value = value;
this.previous = previous;
this.next = next;
}
}
@Override
public Iterator<E> iterator() {
// TODO Auto-generated method stub
return new LinkedIterator();
}
private class LinkedIterator implements Iterator<E> {
Entry<E> current = header;
@Override
public boolean hasNext() {
if (current.previous != header) {
return true;
}
return false;
}
@Override
public E next() {
E e = current.previous.value;
current = current.previous;
return e;
}
}
}
测试代码:
package com.cmcc.review;
public class TestClient {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("t1");
list.add("t2");
list.add("t3");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
LinkedList<String> list1 = new LinkedList<String>();
list1.add("t11");
list1.add("t12");
list1.add("t13");
Iterator<String> iterator1 = list1.iterator();
while (iterator1.hasNext()) {
System.out.println(iterator1.next());
}
}
}
控制台展示:
t1
t2
t3
t11
t12
t13
从结果中可以看出已经实现了遍历的效果。迭代器模式是一个已经没落的模式,很少会有人去专门写一个迭代器,因为迭代器是未容器服务的,为解决遍历这些容器中的元素而诞生的,
而现有使用的容器类都已经是实现了迭代器方法。作为一名java开发人员,尽量不要自己写迭代器模式,使用java提供的Iteraor一般就能满足要求了(特殊情况除外)。
参考大牛博客:http://www.cnblogs.com/zuoxiaolong/p/pattern18.html