1. ArrayList VS LinkedList
1.1 ArrayList
- List 的可增长数组实现
- 优点:对 get 和 set 的调用花费常数时间
- 缺点:插入和删除开销昂贵
1.2 LinkedList
- List的双链表实现
- 优点:插入和删除开销小(若变动项位置已知,花费常数时间)
- 缺点:对 get 的调用开销昂贵
2. ArrayList 的简单实现
ArrayList实现
package chapter2.arrayList;
public class MyArrayList {
private static final int CAPACITY = 10;
private int size;
private Object[] nodes;
public MyArrayList() {
size = 0;
ensureCapacity(CAPACITY); //初始化数组最大容量为10
}
/**
* 确认数组容量是否足够,不够则扩充容量
* 扩充容量开销高,应避免频繁扩容
*
* @param newCapacity 新容量
*/
private void ensureCapacity(int newCapacity) {
if (newCapacity < size) {
return;
}
Object[] oldNodes = nodes;
nodes = new Object[newCapacity];
for (int i = 0; i < size; i++) {
nodes[i] = oldNodes[i];
}
}
/**
* 得到数组大小
*
* @return size
*/
public int size() {
return size;
}
/**
* 判断数组是否为空
*
* @return true or false
*/
public boolean isEmpty() {
return size == 0;
}
/**
* 判断数组是否包含某个元素
*
* @param element 要判断的元素
* @return true or false
*/
public boolean contains(Object element) {
for (int i = 0; i < size; i++) {
if (element.equals(nodes[i]))
return true;
}
return false;
}
/**
* 在数组末尾插入元素
*
* @param element 要插入的元素
*/
public void add(Object element) {
add(size(), element);
}
/**
* 在指定位置插入元素
*
* @param index 插入位置
* @param element 要插入的元素
*/
public void add(int index, Object element) {
ensureCapacity(size * 2 + 1); //容量扩充两倍,避免频繁扩容
for (int i = size; i > index; i--) {
nodes[i] = nodes[i - 1];
}
nodes[index] = element;
size++;
}
/**
* 删除元素
*
* @param index 要删除元素的位置
* @return 被替换的旧元素
*/
public Object remove(int index) {
Object removeElement = nodes[index];
for (int i = index; i < size - 1; i++) {
nodes[i] = nodes[i + 1];
}
//nodes[size-1]=null; 数组大小已经减小1,该节点不会被访问到,没有必要清空
size--;
return removeElement;
}
/**
* 设置元素
*
* @param index 要设置的元素位置
* @param element 要设置的元素
* @return 被替换的旧元素
*/
public Object set(int index, Object element) {
if (index < 0 || index >= size) {
throw new ArrayIndexOutOfBoundsException();
}
Object oldElement = nodes[index];
nodes[index] = element;
return oldElement;
}
/**
* 获取元素
*
* @param index 要获取的元素位置
* @return 获取到的元素
*/
public Object get(int index) {
if (index < 0 || index >= size) {
throw new ArrayIndexOutOfBoundsException();
}
return nodes[index];
}
/**
* 查找某个元素的位置
*
* @param element 要查找的元素
* @return 元素位置(不存在则返回-1)
*/
public int indexOf(Object element) {
for (int i=0;i<size;i++){
if (element.equals(nodes[i])){
return i;
}
}
return -1;
}
/**
* 清空数组
*/
public void clear() {
nodes = null;
size = 0;
}
}
测试类
package chapter2.arrayList;
public class TestArrayList {
public static void main(String args[]){
MyArrayList myArrayList=new MyArrayList();
myArrayList.add("a");
System.out.println("isEmpty:"+myArrayList.isEmpty());
myArrayList.add("b");
myArrayList.add("c");
System.out.println("size:"+myArrayList.size());
printList(myArrayList);
myArrayList.add(1,"d");
printList(myArrayList);
System.out.println("remove: "+myArrayList.remove(2));
//printList(myArrayList);
System.out.println("contains b:"+myArrayList.contains("b"));
System.out.println("replace:"+ myArrayList.set(0,"e"));
printList(myArrayList);
System.out.println("index of d:"+myArrayList.indexOf("d"));
myArrayList.clear();
System.out.println("isEmpty:"+myArrayList.isEmpty());
}
private static void printList(MyArrayList arrayList){
for (int i=0;i<arrayList.size();i++){
System.out.print(arrayList.get(i)+" ");
}
System.out.println();
}
}
输出
isEmpty:false
size:3
a b c
a d b c
remove: b
contains b:false
replace:a
e d c
index of d:1
isEmpty:true
3. LinkedList的简单实现
LinkedList 实现
package chapter2.linkedList;
public class MyLinkedList {
private static class Node {
Node prev;
Node next;
Object element; //节点存储的数据
public Node(Object object, Node p, Node n) {
element = object;
prev = p;
next = n;
}
}
private Node beginMarker; //开始标记节点
private Node endMarker; //结束标记节
private int size;
public MyLinkedList() {
clear();
}
/**
* 得到链表大小
*
* @return size
*/
public int size() {
return size;
}
/**
* 判断链表是否为空
*
* @return true or false
*/
public boolean isEmpty() {
return size == 0;
}
/**
* 判断链表是否包含某个元素
*
* @param element 要判断的元素
* @return true or false
*/
public boolean contains(Object element) {
Node p = beginMarker;
for (int i = 0; i < size; i++) {
p = p.next;
if (p.element.equals(element)) {
return true;
}
}
return false;
}
/**
* 在链表末尾插入元素
*
* @param element 要插入的元素
*/
public void add(Object element) {
add(size, element);
}
/**
* 在指定位置插入元素
*
* @param index 插入位置
* @param element 要插入的元素
*/
public void add(int index, Object element) {
addBefore(getNode(index),element);
}
/**
* 在某一节点前插入元素
*
* @param node 该节点
* @param element 要插入的元素
*/
private void addBefore(Node node, Object element) {
Node newNode = new Node(element, node.prev, node);
node.prev.next = newNode;
node.prev = newNode;
size++;
}
/**
* 删除节点
*
* @param index 要删除节点的位置
* @return 被替换的旧节点的element
*/
public Object remove(int index) {
Node oldNode=getNode(index);
remove(oldNode);
return oldNode.element;
}
/**
* 删除节点
*
* @param node 要删除的节点
* @return 被删除的节点的element
*/
private Object remove(Node node){
node.prev.next=node.next;
node.next.prev=node.prev;
size--;
return node.element;
}
/**
* 设置元素
*
* @param index 要设置的元素位置
* @param element 要设置的元素
* @return 被替换的旧元素
*/
public Object set(int index, Object element) {
Node node = getNode(index);
Object oldElement = node.element;
node.element = element;
return oldElement;
}
/**
* 获取元素
*
* @param index 要获取的元素位置
* @return 获取到的元素
*/
public Object get(int index) {
return getNode(index).element;
}
/**
* 查找某个元素的位置
*
* @param element 要查找的元素
* @return 元素位置(不存在则返回-1)
*/
public int indexOf(Object element) {
Node p = beginMarker;
for (int i = 0; i < size; i++) {
p = p.next;
if (p.element.equals(element)) {
return i;
}
}
return -1;
}
/**
* 清空数组
*/
public void clear() {
size = 0;
beginMarker = new Node(null, null, null);
endMarker = new Node(null, beginMarker, null);
beginMarker.next = endMarker;
}
private Node getNode(int index) {
Node p;
if (index < 0 || index > size) {
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;
}
}
return p;
}
}
测试类(测试用例与上面 ArrayList 完全相同)
package chapter2.linkedList;
class TestLinkedList {
public static void main(String args[]) {
MyLinkedList myLinkedList = new MyLinkedList();
myLinkedList.add("a");
System.out.println("isEmpty:" + myLinkedList.isEmpty());
myLinkedList.add("b");
myLinkedList.add("c");
System.out.println("size:" + myLinkedList.size());
printList(myLinkedList);
myLinkedList.add(1, "d");
printList(myLinkedList);
System.out.println("remove: " + myLinkedList.remove(2));
//printList(myArrayList);
System.out.println("contains b:" + myLinkedList.contains("b"));
System.out.println("replace:" + myLinkedList.set(0, "e"));
printList(myLinkedList);
System.out.println("index of d:" + myLinkedList.indexOf("d"));
myLinkedList.clear();
System.out.println("isEmpty:" + myLinkedList.isEmpty());
}
/*打印链表*/
private static void printList(MyLinkedList linkedList){
for (int i=0;i<linkedList.size();i++){
System.out.print(linkedList.get(i)+" ");
}
System.out.println();
}
}
输出(与上面 ArrayList 的输出完全相同)
isEmpty:false
size:3
a b c
a d b c
remove: b
contains b:false
replace:a
e d c
index of d:1
isEmpty:true