实现ArrayList ,LinkedList 的基本功能

参考 尚学堂 Java 300 集点击打开链接 和一些文档 点击打开链接




概念:

一 、什么是 List

  List 是有序、可重复的容器。

      有序:List 中每个元素都有索引标记。可以根据元素的索引标记(在List中的位置)访问元素,从而精确控制这些元素。

      可重复:List 允许加入重复的元素。更确切地讲,List通常允许满足 e1.equals(e2) 的元素重复加入容器(set就不行,可以将set理解为数学的集合)

      List 接口常用的三个实现类 ArrayList、LinkedList、Vector。这三个都满足上面的两个条件

 二、List 的基本功能(常用的一些方法)

三、ArrayList、LinkedList、Vector 的特点与不同

ArrayList 底层实现是数组进行存储,因此特点是查询快,增/删操作慢,线程不安全

LinkedList 底层实现是链表进行存储,因此特点是查询慢,增/删操作快,线程不安全

Vector 底层是数组实现的 List ,相关的方法增加了同步检查(synchronized),因此线程安全,效率低

因此运用时,需要线程安全,就用 Vector

                    不需要考虑线程安全,但是查询较多,使用 ArrayList

                    不需要考虑线程安全,但是增/删较多,使用 LinkedList


四、代码实现(简单的功能,里面有bug)

ArrayList:

package cn.swu.stormliu.test;

public class MyArrayList {
	int size;
	Object value[];
	public MyArrayList() {
		this(10);
	}
	public MyArrayList(int initCapacity) {
		if(initCapacity<0) {
			try {
				throw new Exception();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		
		}
		value=new Object[initCapacity];
		
	}
	public void add(Object obj) {
		ensureCapacity();
		value[size]=obj;
		size++;
	}
	public void ensureCapacity() {
		if(size==value.length) {
			Object newArrayList []=new Object [size*2+1];
			System.arraycopy(value, 0, newArrayList, 0, value.length	);
			value=newArrayList;
		}
		
	}
	public boolean  isEmpty() {
		
		return size==0;
	}
	public boolean remove(Object obj) {
		if(obj==null) {
			for(int i=0;i<size;i++) {
				if(value[i]==null) {
					fastRemove(i);
					return true;
				}
			}
		}else {
			for(int i=0;i<size;i++) {
				if(obj.equals(value[i])) {
					fastRemove(i);
					return true;
				}
			}
		}
		return false;
	}
	public void remove(int index) {
		rangeCheck(index);
		fastRemove(index);
		
	}
	public void fastRemove(int index) {
		int numMoved=size-index-1;
		if(numMoved>0)
		System.arraycopy(value, index+1, value, index, numMoved);
		value[--size]=null;
	}
	public Object get(int index) {
		rangeCheck(index);
		return value[index];
	}
	private void  rangeCheck(int index) {
		if(index<0||index>=size) {
			try {
				throw new Exception();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	public Object set(int index,Object obj) {
		rangeCheck(index);
		
		Object oldValue = value[index];
        value[index] = obj;
        return oldValue;
        }
	public void add(int index,Object obj) {
		rangeCheck(index);
		ensureCapacity();
		System.arraycopy(value, index, value, index+1, size-index);
		value[index]=obj;
		size++;
	}
	public static void main(String[] args) {
		MyArrayList list=new MyArrayList(4);
		list.add("456");
		list.add("adsf");
		list.add("sdf");
		list.add("s678");
		list.set(3, "sajdfl");
		list.add(1, "123465");
		for(int i=0 ;i<list.size;i++) {
			System.out.println(list.get(i));
		}
		
	}
	
}
 
 

运行结果:

ArrayList 每次的增/删操作都需要将原来数组的插入点的后面全部复制一遍,因此,代价很高,

但是查询,只需要将地址传入,很快便能计算出地址,直接查找

LinkedList:

定义链表的节点:

class Node{
	 Node previous;
	 Object obj;
	 Node next;
	public Object getPrevious() {
		return previous;
	}
	
	public Node(Node previous, Object obj, Node next) {
		super();
		this.previous = previous;
		this.obj = obj;
		this.next = next;
	}

	public Object getObj() {
		return obj;
	}

	public void setObj(Object obj) {
		this.obj = obj;
	}

	public Node getNext() {
		return next;
	}

	public void setNext(Node next) {
		this.next = next;
	}

	public void setPrevious(Node previous) {
		this.previous = previous;
	}

	public Node() {
		
	}
}


 链表的插入:

1、找到插入的位置的节点 temp,获取上一个节点的信息 up

2、将上一个节点的next 指定为新节点,将新节点的 previous 指定为上一个节点

3、将新节点的 next 指向temp;temp的previous 指向新节点

4、将传入的数据存储到新节点的 obj


	public void add(int index,Object obj) {
		rangeCheck(index);
		Node temp=node(index);	//用来存储临时节点
		if(temp!=null) {
			Node newNode=new Node();//创建新节点
			newNode.obj=obj;
			Node up=temp.previous;	//找到插入节点的上一个节点 并命名为up
			up.next=newNode;		
			newNode.previous=up;
			newNode.next=temp;
			temp.previous=newNode;
			size++;
		}
	}

链表的删除:






1、找到删除的节点temp(b),获取上一个节点信息 up (a),下一个节点信息 down(c)

2、将up 的 next 指向 down,将down 的previous 指向 up

 
 
 
 
public void remove(int index) {
		rangeCheck(index);
		Node temp=node(index);
		if(index<size-1) {
			if(temp!=null) {
				Node up=temp.previous;
				Node down=temp.next;
				up.next=down;
				down.previous=up;
					
				size--;
			}
		}else {
			if(temp!=null) {
				Node up=temp.previous;
				Node down=null;
				up.next=null;
				last=up;
				size--;
			}
		}
	}

LinkedList 基本功能和主程序:

public class MyLinkedList {
	private Node first;
	private Node last;
	private int size;
	
	public void add(Object obj) {
		Node n=new Node();
		if(first==null) {
			n.setObj(obj);
			n.setPrevious(null);
			n.setNext(null);
			first=n;
			last=n;
		}else {
			
			n.setPrevious(last);
			n.setObj(obj);
			n.setNext(null);
			last.setNext(n);
			last=n;
		}
		size++;
		
	}
	public int size() {
		return size;
	}
	public void rangeCheck(int index) {
		if(index<0||index>=size) {
			try {
				throw new Exception();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
		}
	}
	
	public Object get(int index) {
		rangeCheck(index);
		Node temp=node(index) ;
		if(temp!=null) {
		return temp.obj;
		}
		return null;
	}
	
	public Node node(int index) {
		Node temp=null;
		if(first!=null)  {
			temp=first;
			for(int i=0;i<index;i++) {
				temp=temp.next;
				
			}
		}
		return temp;
	}
	
	public void remove(int index) {
		rangeCheck(index);
		Node temp=node(index);
		if(index<size-1) {
			if(temp!=null) {
				Node up=temp.previous;
				Node down=temp.next;
				up.next=down;
				down.previous=up;
					
				size--;
			}
		}else {
			if(temp!=null) {
				Node up=temp.previous;
				Node down=null;
				up.next=null;
				last=up;
				size--;
			}
		}
	}
	public void set(int index,Object obj) {
		rangeCheck(index);
		Node temp=node(index);
		if(temp!=null) {
		Node newnode=new Node();
		newnode.obj=obj;
		
		Node up=temp.previous;
		up.next=newnode;
		newnode.previous=up;
		
		Node down=temp.next;
		down.previous=newnode;
		newnode.next=down;
	}
	}
	public void add(int index,Object obj) {
		rangeCheck(index);
		Node temp=node(index);
		if(temp!=null) {
			Node newNode=new Node();
			newNode.obj=obj;
			Node up=temp.previous;
			up.next=newNode;
			newNode.previous=up;
			newNode.next=temp;
			temp.previous=newNode;
			size++;
		}
	}
	
	public static void main(String[] args) {
		MyLinkedList list =new MyLinkedList();
		list.add("aaa");
		list.add("bbb");
		list.add("5645");
		list.add(1,"1564798");
		for(int i=0;i<list.size;i++)
		System.out.println(list.get(i));
		
	}
	
}

 运行结果:




链表的 增/删 不涉及数据的移动,只需要将指向指定好即可,因此代价很小。但是查找需要一个一个遍历

(可以比较查找的index 和 链表的 size/2 进行比较 ,大于则从 last 遍历,反之则从 first遍历)。

猜你喜欢

转载自blog.csdn.net/qq_35583772/article/details/80355584