Java深入理解ArrayList 和LinkList

学习java容器这块儿,不仅仅要掌握基本的使用方法,而且在这些底层实现上必须深入.

对于ArrayList底层实现是对象数组,相信写过String类<相关介绍:https://blog.csdn.net/qq_41681241/article/details/84329841>的朋友都知道,其底层也是通过字符数组实现的,所以ArrayList实现原理和它差不多.如下代码,仅供参考.在类里面定义Object 数组,因为Object是所有类的父类,可以利用父类可以引用子类的实例这一特性来实现ArrayList对任意对象的存储,其中size是记录ArrayList的计数器,记录ArraList里面存的元素个数.在定义ArrayList对象时,ArrayList类中会初始化一个数组的大小,然后,size到时候要是超过这个值,就定义容量更大的数组,并复制原数组中的所有元素,即通过System.arraycopy(原数组, 元数据起始复制点,新数组 ,新数组的起始位置,copy的长度)到新的数组,并继续添加元素,最后,直接将新数组赋值给旧数组.实现remove方法也是使用arraycopy这一方法实现.

import java.util.ArrayList;
import java.util.List;

class MArrayList {

	private Object[] elements;

	private int size;

	public MArrayList() {
		this(10);
	}

	public MArrayList(int num) {
		size = 0 ;
		if(num <= 0) {
		try {
				throw new Exception() ;
		}catch(Exception e){
			e.printStackTrace();
		}
		
		elements = new Object[num] ;
	}

	public void add(Object ob) {

		// 数组扩容
		if (size > elements.length) {

			Object[] newArray = new Object[size * 2 + 1];
			System.arraycopy(elements, 0, newArray, 0, elements.length);
			elements = newArray;
		}
		elements[size++] = ob;
	}

	public boolean isEmpty() {
		return size == 0 ? true : false;
	}

	public Object get(int index) {

		check(index);
		return elements[index];
	}

	public void check(int index) {

		if (index < 0 || index >= size) {
			try {
				throw new Exception();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public void remove(int index) {
	
		// 删除指定位置的对象
		int len = elements.length;
		check(index);
		Object[] array = new Object[len];
		System.arraycopy(elements, index, array, index, size - index - 1);
		elements = array;
		elements[--size] = null;
	}

	public void remove(Object o) {
		for (int i = 0; i < elements.length; i++) {
			// 底层调用equals 方法
			if (get(i).equals(o)) {
				remove(i);
			}
		}
	}

	public Object set(int index, Object o) {
		check(index);
		Object old = elements[index];
		elements[index] = o;
		return old;
	}

	void add(int index, Object obj) {

		int len = elements.length;
		if (size + 1 >= len) {
			len = 2 * len + 1;
			Object[] array = new Object[len];
			System.arraycopy(elements, 0, array, 0, size);
			array[++size] = obj;
			elements = array;
		} else {
			elements[++size] = obj;
		}
	}
}

 

 LinkedList实现就像和c语言链表的实现差不多,定义一个Node对象,含有前驱和后继,还有数据域,即Object对象.下面是代码实现.实现的是双向链表.在按照索引查找这块第一次的实现策略是通过遍历整个链表来找相等索引的数据,第二种策略是按照折半的思想来照相关索引值.第二种策略更加高效.

class Node {

	private Node previous;
	private Node next;
	private Object obj;

	public Node getPrevious() {
		return previous;
	}

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

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

	public Node getNext() {
		return next;
	}

	public Object getObj() {
		return obj;
	}

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

public class Main {

	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);

			first = n;
			last = n;
		} else {
			n.setPrevious(last);
			n.setObj(obj);
			n.setNext(null);
			last.setNext(n);
			last = n;
		}
		size++;
	}

	public Object get(int index) {
		check(index);
//这样遍历链表找元素不高效
//		if (first == null) {
//			return null;
//		}
//		Node temp = first;
//		int count = 0;
//		while (temp != null) {
//
//			if (count == index) {
//				break;
//			}
//			temp = temp.getNext();
//			count++;
//		}
//
//		// index越界如何处理
//		return temp.getObj();

		//使用折半的思想找元素
		//size向右移一位,即size/2,当index小于这个值时,从前开始遍历链表
		//否则从后开始遍历链表
		
		if(index <= (size>>1)) {
			Node temp = first ;
			int count =0 ;
			while(temp!=null) {
				if(count == index) {
					return temp.getObj();
				}
				count++ ;
				temp = temp.getNext();
			}
		}
		else {
			Node temp = last ;
			int count =size-1;
			while(temp!=null) {
				if(count==index) {
					return temp.getObj();
				}
				count-- ;
				temp = temp.getPrevious() ;
			}
		}
		return null ;
	}

	public Node node(int index) {
		Node temp = null;
		if (first != null) {
			temp = first;
		}
		for (int i = 0; i != index; i++) {
			temp = temp.getNext();
		}
		return temp;
	}

	public void remove(int index) {

		check(index);
		Node temp = first;

		temp = node(index);
		if (temp == first) {

			first = temp.getNext();
			first.setPrevious(null);
			return;
		} else {
			Node tt = temp.getNext();
			temp.setNext(tt.getNext());
			tt.setPrevious(temp);
			return;
		}
	}

	public void add(int index, Object obj) {
		Node temp = node(index);
		if (temp != null) {
			Node tt = temp.getNext();
			Node newNode = new Node();
			newNode.setObj(obj);
			newNode.setNext(tt);
			tt.setPrevious(newNode);
			temp.setNext(newNode);
			newNode.setPrevious(temp);
		}
	}

	public int size() {

		return size;
	}

	public void check(int index) {

		if (index < 0 || index >= size) {
			try {
				throw new Exception();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	public static void main(String[] arg) {

		Main ls = new Main();
		ls.add("aaa");
		ls.add("ddd");
		System.out.println(ls.get(0));
		System.out.println(ls.get(1));
	}
}

 

posted @ 2019-02-20 10:38  渣渣班  阅读(656)  评论(0)    收藏  举报