Java之实现自己的ArrayList与LinkedList
来源:互联网 发布:钱箱软件 编辑:程序博客网 时间:2024/06/05 15:10
我们知道List
接口的两个常用实现类为ArrayList
与LinkedList
。
ArrayList
底层采用数组实现,随机访问元素非常快,只需要常数时间c。但是对于删除和插入元素则比较耗时,因为它需要移动元素,需要线性时间,即O(N)。
而LinkedList
底层采用链表实现,它的插入与删除操作非常快,只是更改两个指针的指向,所以 需要花常数时间c。但是随机访问则比较耗时,因为它需要从头节点或者尾节点进行依次地遍历,需要线性时间,即O(N)。
现在呢,我们就采用数组和链表分别实现自己MyArrayList
与MyLinkedList
。当然,这里只是实现最基础的功能。
1.MyArrayList
MyArrayList
的默认大小为10。每次扩充数组的时候在原有的基础上乘以2再加1。加1是防止数组大小为0的情况。
package myList;import java.util.Iterator;import java.util.NoSuchElementException;public class MyArrayList<T> implements Iterable<T> { // 默认容量 private static final int DEFAULT_CAPACITY = 10; //实际大小 private int theSize; // 数组 private T[] theItems; public MyArrayList() { doClear(); } public int size(){ return theSize; } public boolean isEmpty(){ return size() == 0; } /** * 清除多余空间 */ public void trimToSize(){ ensureCapacity(size()); } /** * 根据索引获取元素 * @param index * @return */ public T get(int index){ if(index < 0 || index >= size()){ throw new IndexOutOfBoundsException(); } return theItems[index]; } /** * 设置新值,返回旧值 * @param index * @param newVal * @return */ public T set(int index, T newVal){ if(index < 0 || index >= size()){ throw new IndexOutOfBoundsException(); } T oldVal = theItems[index]; theItems[index] = newVal; return oldVal; } /** * 根据索引添加元素 * @param index * @param x */ public void add(int index, T x){ // 扩展容量 if(theItems.length == size()){ ensureCapacity(size() * 2 + 1); } // 向后移动 for(int i = theSize;i > index;i--){ theItems[i] = theItems[i-1]; } // 添加 theItems[index] = x; // 实际容量增加1 theSize++; } /** * 默认向最后添加 * @param x * @return */ public boolean add(T x){ add(size(), x); return true; } /** * 根据索引删除节点 * @param index * @return */ public T remove(int index){ T removedItem = theItems[index]; // 向前移动 for(int i = index;i<size()-1;i++){ theItems[i] = theItems[i+1]; } //实际容量减小1 theSize--; return removedItem; } private void doClear(){ theSize = 0; ensureCapacity(DEFAULT_CAPACITY); } /** * 数组扩展 * @param newCapacity */ public void ensureCapacity(int newCapacity){ if(newCapacity < theSize){ return; } T[] old = theItems; // 泛型不能实例化,只能这么写 theItems = (T[])new Object[newCapacity]; for(int i = 0;i<size();i++){ theItems[i] = old[i]; } } /** * 迭代器方法 */ @Override public Iterator<T> iterator() { return new ArrayListIterator(); } /** * 迭代器。内部类 * @author Gavin * */ private class ArrayListIterator implements Iterator<T>{ private int current = 0; @Override public boolean hasNext() { return current < size(); } @Override public T next() { // 如果已经没有元素了 if(!hasNext()){ throw new NoSuchElementException(); } return theItems[current++]; } public void remove(){ MyArrayList.this.remove(--current); } } @Override public String toString() { StringBuilder line = new StringBuilder("["); for(int i = 0;i<size();i++){ line.append(theItems[i]); if(i != size()-1){ line.append(", "); }else{ line.append("]"); } } return line.toString(); }}
2.MyLinkedList
MyLinkedList
采用双向链表实现。具有头节点和尾节点,头节点没有前驱结点,而尾节点没有后继节点。
package myList;import java.util.ConcurrentModificationException;import java.util.Iterator;import java.util.NoSuchElementException;public class MyLinkedList<T> implements Iterable<T>{ /** * 节点类 * @author Gavin * * @param <T> */ private static class Node<T>{ public T data; public Node<T> prev; public Node<T> next; public Node(T data,Node<T> prev, Node<T> next) { this.data = data; this.prev = prev; this.next = next; } } // 实际数据量 private int theSize = 0; // 该变量用于迭代时的判断 private int modCount = 0; // 头节点 private Node<T> beginMarker; // 尾节点 private Node<T> endMarker; public MyLinkedList(){ doClear(); } public void clear(){ doClear(); } public void doClear(){ beginMarker = new Node<T>(null, null, null); endMarker = new Node<T>(null, beginMarker, null); beginMarker.next = endMarker; theSize = 0; modCount ++; } /** * size()方法,返回实际的数据量大小 * @return */ public int size(){ return theSize; } /** * 判断是否为空 * @return */ public boolean isEmpty(){ return size() == 0; } /** * 私有方法。在节点p之前插入新节点,数据为x * @param p * @param x */ private void addBefore(Node<T> p, T x){ Node<T> newNode = new Node<T>(x, p.prev, p); newNode.prev.next = newNode; p.prev = newNode; theSize++; modCount++; } /** * 私有方法。寻找Node,索引在lower和upper之间 * @param index * @param lower * @param upper * @return */ private Node<T> getNode(int index, int lower,int upper){ Node<T> p; if(index < lower || index > upper){ throw new IndexOutOfBoundsException(); } //如果是在前半段,就从前往后寻找 if(index < size()/2){ p = beginMarker.next; for(int i = 0;i<index;i++){ p = p.next; } } // 如果是在后半段,就从后往前寻找 else{ p = endMarker; for(int i = size();i>index;i--){ p = p.prev; } /*这里为什么不采用这种写法,是因为upper的值有可能为size() p = endMarker.prev; for(int i = size()-1;i>index;i--){ p = p.prev; } */ } return p; } /** * 私有方法。该方法限制index在0和size()-1之间 * @param index * @return */ private Node<T> getNode(int index){ return getNode(index, 0, size()-1); } /** * 根据index索引获取值 * @param index * @return */ public T get(int index){ return getNode(index).data; } /** * 设置某一个index索引位置上的值 * @param index * @param newVal * @return */ public T set(int index, T newVal){ Node<T> p = getNode(index); T oldVal = p.data; p.data = newVal; return oldVal; } /** * 这里的index可能为0到size()之间 * @param index * @param x */ public void add(int index,T x){ addBefore(getNode(index,0,size()), x); } /** * 该add方法直接调用add(index,x),并且index为size() * @param x * @return */ public boolean add(T x){ add(size(), x); return true; } /** * 私有方法。删除一个节点Node * @param p * @return */ private T remove(Node<T> p){ p.prev.next = p.next; p.next.prev = p.prev; theSize--; modCount++; return p.data; } /** * 根据索引删除节点 * @param index * @return */ public T remove(int index){ return remove(getNode(index)); } /** * 迭代器方法 */ @Override public Iterator<T> iterator() { return new LinkedListIterator(); } /** * 迭代器。内部类 * @author Gavin * */ private class LinkedListIterator implements Iterator<T>{ private Node<T> current = beginMarker.next; //此变量用于限制遍历期间,MyLinkedList不能修改 private int expectedModCount = modCount; //此变量用于限制不能多次remove private boolean okToRemove = false; @Override public boolean hasNext() { return current != endMarker; } @Override public T next() { if(modCount != expectedModCount){ throw new ConcurrentModificationException(); } if(!hasNext()){ throw new NoSuchElementException(); } T nextItem = current.data; current = current.next; okToRemove = true; return nextItem; } public void remove(){ if(modCount != expectedModCount){ throw new ConcurrentModificationException(); } if(!okToRemove){ throw new IllegalStateException(); } MyLinkedList.this.remove(current.prev); expectedModCount++; okToRemove = false; } } @Override public String toString() { StringBuilder line = new StringBuilder("["); Node<T> p = beginMarker.next; while(p!=endMarker.prev){ line.append(p.data); line.append(", "); p = p.next; } line.append(p.data); line.append("]"); return line.toString(); }}
0 0
- Java之实现自己的ArrayList与LinkedList
- [Java]ArrayList与LinkedList的模拟实现
- java-----容器类总结之ArrayList与LinkedList的区别
- java基础之ArrayList与LinkedList以及Vector的区别
- Java基础之ArrayList与LinkedList
- java基础知识总结之arrayList与linkedList
- JAVA集合之---LinkedList、ArrayList与Vector
- Java之--ArrayList、LinkedList
- java自己实现的linkedlist
- java:ArrayList,Vector,LinkedList的实现
- java中的ArrayList与LinkedList的区别
- java中ArrayList与LinkedList的比较
- Java中ArrayList与LinkedList的区别
- 【Java】 ArrayList与LinkedList的区别
- ArrayList 与 LinkedList 底层实现
- 数据结构-Java实现-ArrayList&LinkedList
- java ArrayList与LinkedList知识点
- Java下ArrayList 与 LinkedList
- -04-LVDS输入接口设计【Xilinx-LVDS读写功能实现】
- jQuery AJAX 方法 success()后台传来的4种数据
- Oracle 约束的定义
- windown git安装
- 分布式日志收集并统计分析
- Java之实现自己的ArrayList与LinkedList
- react学习笔记(1)
- Activiti HelloWorld实现
- jQuery中extend函数详解
- C++ 智能指针详解
- sql中的limit的用法
- CA认证简单介绍和工作流程
- 终于看完了第三部分
- 构造方法私有化