博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java集合之ArrayList和LinkedList的实现原理以及Iterator详解
阅读量:5352 次
发布时间:2019-06-15

本文共 6741 字,大约阅读时间需要 22 分钟。

ArrayList实现可变数组的原理:

  当元素超出数组内容,会产生一个新数组,将原来数组的数据复制到新数组中,再将新的元素添加到新数组中。

  ArrayList:是按照原数组的50%来延长,构造一个初始容量为10的空列表

用ArrayList模拟数组:

1 package iterater.patten.design; 2  3 //探索ArrayList实现的可变数组的原理,用ArrayList实现一个容器存储对象 4 public class ArrayList { 5     Object[] objects = new Object[10]; 6     // 定义计数器,用于计算数组中的元素个数 7     int index = 0; 8  9     public void add(Object o) {10         // 当数组满时,则创建一个新的数组,将原数组中的元素复制进新数组中,再将新的元素加入到数组中11         if (index == objects.length) {12             // 按原数组的2倍长度创建新数组,其实这样不太合理13             Object[] newObjects = new Object[objects.length * 2];14             // 将原数组中的元素复制进新数组中,再将新的元素加入到数组中15             System.arraycopy(objects, 0, newObjects, 0, objects.length);16             // 数组引用指向新的数组17             objects = newObjects;18         }19 20         // 将新增元素放到数组中21         objects[index] = o;22         index++;23     }24 25     // 定义size函数获取元素个数26     public int size() {27         return index;28     }29 }

  用LinkedList模拟数组

1 package iterater.patten.design; 2  3 //探索LinkedList实现的可变数组的原理,用LinkedList实现一个容器存储对象 4 public class LinkedList { 5  6     //定义链表的头指针head以及尾指针tail 7     Node head = null; 8     Node tail = null; 9     int size = 0;10 11     //添加元素12     public void add(Object o) {13         //一个新的结点14         Node n = new Node(o, null);15         //当链表为空时,head指向新添加的结点,tail也指向该结点16         if (head == null) {17             head = n;18             tail = n;19         }20         //链表不为空时,tail包含的下一个结点的引用指向这个新加入的结点21         22         tail.setNext(n);23         tail = n;24         size++;25     }26 27     public int size() {28         return size;29     }30 }

  Node结点的类定义 

1 package iterater.patten.design; 2  3 //定义一个类来存储链表中的结点 4 public class Node { 5  6     private Object data; 7     private Node next; 8     public Object getData() { 9         return data;10     }11     public void setData(Object data) {12         this.data = data;13     }14     public Node getNext() {15         return next;16     }17     public void setNext(Node next) {18         this.next = next;19     }20     public Node(Object data, Node next) {21         super();22         this.data = data;23         this.next = next;24     }25     26 }

  添加的元素对象所属的类的类定义

1 package iterater.patten.design; 2  3 public class Cat { 4  5     private int id; 6  7     public int getId() { 8         return id; 9     }10 11     public void setId(int id) {12         this.id = id;13     }14 15     public Cat(int id) {16         super();17         this.id = id;18     }19 }

  测试类 

1 package iterater.patten.design; 2  3 import iterater.patten.design.*; 4  5 public class IteratorTest { 6  7     /** 8      * @param args 9      */10     public static void main(String[] args) {11 12         // ArrayList al=new ArrayList();13         LinkedList al = new LinkedList();14         for (int j = 0; j < 15; j++) {15             al.add(new Cat(j));16         }17         System.out.println(al.size());18     }19 20 }

  输出结果:15

【温情提示】:我们在测试类中为了提高容器的可替换性,可以定义一个接口Collection,定义add、size方法,只要保证容器类实现该接口,当用户使用add添加元素或者使用size获取元素个数的时候就可以更加方便(因为如果ArrayList中的添加元素方法叫add,而LinkedList中添加元素的方法叫addall,用户在使用的时候就会造成困扰,使用定义接口的方式,我们只对接口进行编程使用,不用去关心具体的实现内容。

  代码实现:

1 public interface Collection {2 3     public Object add(Object o);4     public int size();5 }

  ArrayList和LinkedList实现该接口,并覆盖抽象方法即可,测试类中可以这样使用两个方法:

  Collection c=new ArrayList();

  c.add(object)、c.size();

  父接口引用指向子类对象,并调用子类中覆盖的方法

  但是此时又出现了一个新的问题,当我们想要对数组中的元素进行遍历时,因为不同的集合有不同的遍历方法,用ArrayList模拟的数组可以通过数组的下标索引进行遍历,但是LinkedList使用的却是另外一种方法。

针对这样的问题,解决的方法就是定义Iterator接口,里面封装了遍历数组元素的统一方式,话不多说,代码来验证。

  定义两个接口Collection和Iterator

1 public interface Collection {2 3     Iterator iterator();4 }

 

1 public interface Iterator {2 3     public boolean hasNext();4     public Object next();5 }

   不同的容器实现Iterator接口,获取具体的迭代器对象(即该容器类型的对象)

1     //具体的实现类,不同的容器,拥有不同的迭代元素的方法 2     private class ArrayListIterator implements Iterator{ 3         private int currentIndex=0; 4         @Override 5         public boolean hasNext() { 6             if(currentIndex>=index){ 7                  8                 return false; 9             }10             else {11                 return true;12             }13         }14 15         @Override16         public Object next() {17             Object object=objects[currentIndex];18             currentIndex++;19             return object;20         }21     }

  只要ArrayList实现我前面自定义的Collection接口,覆盖iterator方法,就可以获取一个具体的实现类的对象

      public class ArrayList implements Collection

1 public Iterator iterator() {2         3         return new ArrayListIterator();4     }

  此时测试类可以这样写

1 package iterater.patten.design; 2  3 import iterater.patten.design.*; 4  5 public class IteratorTest { 6  7     /** 8      * @param args 9      */10     public static void main(String[] args) {11 12         ArrayList al = new ArrayList();13         for (int j = 0; j < 15; j++) {14             al.add(new Cat(j));15         }16         Iterator it = al.iterator();17         while (it.hasNext()) {18             Object object = it.next();19             System.out.print(object + " ");20         }21         System.out.println();22     }23 24 }

  迭代器Iterator的实现原理大致就是这样,尽管不同的集合内部的数据结构不同,统一了遍历集合的方式。

  最后附上ArrayList的类的代码:

1 package iterater.patten.design; 2  3  4 //探索ArrayList实现的可变数组的原理,用ArrayList实现一个容器存储对象 5 public class ArrayList implements Collection{ 6     Object[] objects = new Object[10]; 7     // 定义计数器,用于计算数组中的元素个数 8     int index = 0; 9 10     public void add(Object o) {11         // 当数组满时,则创建一个新的数组,将原数组中的元素复制进新数组中,再将新的元素加入到数组中12         if (index == objects.length) {13             // 按原数组的2倍长度创建新数组,其实这样不太合理14             Object[] newObjects = new Object[objects.length * 2];15             // 将原数组中的元素复制进新数组中,再将新的元素加入到数组中16             System.arraycopy(objects, 0, newObjects, 0, objects.length);17             // 数组引用指向新的数组18             objects = newObjects;19         }20 21         // 将新增元素放到数组中22         objects[index] = o;23         index++;24     }25 26     // 定义size函数获取元素个数27     public int size() {28         return index;29     }30     //不同的容器,拥有不同的迭代元素的方法31     private class ArrayListIterator implements Iterator{32         private int currentIndex=0;33         @Override34         public boolean hasNext() {35             if(currentIndex>=index){36                 37                 return false;38             }39             else {40                 return true;41             }42         }43 44         @Override45         public Object next() {46             Object object=objects[currentIndex];47             currentIndex++;48             return object;49         }50     }51 52     @Override53     public Iterator iterator() {54         55         return new ArrayListIterator();56     }57 58 }
View Code

 

转载于:https://www.cnblogs.com/ysw-go/p/5383498.html

你可能感兴趣的文章
父类和子类的关系、代码例子
查看>>
多设备分发测试
查看>>
6月2日第九次会议
查看>>
jquery的ajax与spring mvc对接注意事项
查看>>
常见问题3:自适应大小高度与宽度
查看>>
JAVA API 之包装类、数学类和 Calendar 类
查看>>
Nice writing
查看>>
mysql系列安装
查看>>
(4) openssl rsa/pkey(查看私钥、从私钥中提取公钥、查看公钥)
查看>>
aes 加密,解密(2)
查看>>
项目中的乱七八糟
查看>>
Spring注解&Aop
查看>>
关于xamarin.forms Android创建文件与写文件 (ftp)
查看>>
Linux一键安装PHP/JAVA环境OneinStack
查看>>
【开源项目8】Android开源项目分类汇总【畜生级别】
查看>>
UI自动化笔记(四):框架搭建
查看>>
我的jlink破解失败经历
查看>>
The STM32F746G-DISCO discovery board -- MBED
查看>>
软重启
查看>>
JavaWeb之XML详解
查看>>