LinkedList相比于之前的ArrayList它的查询的效率要比ArrayList差但是它的添加和删除效率要比ArrayList好。LinkedList底层是通过链表实现的,所谓链表就是一系列存储数据元素的单元通过指针串接起来形成的。在链表里面,每个单元至少有两个域,一个域用于数据元素的存储,另一个域是指向其他单元的指针。这个单元在链表中我们称之为节点。在单链表中每个节点都会保存一个指向下一个节点的指针。下面我用java代码通过单链表数据结构实现List接口。
首先定义一个节点接口:
public interface Node { public Object getData(); public void setDate(Object data); }
编写一个节点接口的实现:
public class SLNodel implements Node{ private Object element; private SLNodel next; public SLNodel() { } public SLNodel(Object element, SLNodel next) { this.element = element; this.next = next; } public SLNodel getNext() { return next; } public void setNext(SLNodel next) { this.next = next; } @Override public Object getData() { return element; } @Override public void setDate(Object data) { element = data; } }
使用单链表实现LinkedList
public class LinkedSList<E> implements List<E>{ private SLNodel head; private int size; public LinkedSList() { head = new SLNodel(); size=0; } @Override public int size() { return size; } @Override public boolean isEmpty() { return size==0; } @Override public boolean contains(Object o) { SLNodel p = head; while (p.getNext()!=null){ if(p.getData().equals(o)){ return true; } p = p.getNext(); } return false; } @Override public boolean add(E e) { if(size==0){ head.setDate(e); head.setNext(new SLNodel()); size++; return true; }else{ SLNodel p = head; while (p.getNext()!=null){ SLNodel target = p.getNext(); if(target.getData()==null){ target.setDate(e); target.setNext(new SLNodel()); size++; return true; }else{ p = p.getNext(); } } } return false; } @Override public boolean remove(Object o) { int index = indexOf(o); if(index!=-1){ remove(index); return true; } return false; } @Override public E get(int index) { if(index<0||index>size-1){ return null; } SLNodel p = head; int i =0; while (p.getNext()!=null){ if(index==i){ return (E)p.getData(); }else{ p = p.getNext(); i++; } } return null; } @Override public E set(int index, E element) { if(index<0||index>size-1){ return null; } SLNodel p = head; int i =0; while (p.getNext()!=null){ if(index==i){ p.setDate(element); return element; }else{ p = p.getNext(); i++; } } return null; } @Override public void add(int index, E element) { if (index < 0 || index > size - 1) { throw new RuntimeException("索引越界"); }else if(index==0){ SLNodel p = new SLNodel(element,head); head=p; size++; }else{ SLNodel p = head; int i = 0; while (p.getNext() != null) { if (index-1 == i) { //前驱节点 SLNodel q =new SLNodel(element,p.getNext()); p.setNext(q); size++; return; } else { p = p.getNext(); i++; } } } } @Override public E remove(int index) { if (index < 0 || index > size - 1) { throw new RuntimeException("索引越界"); }else if(index==0){ E e = (E)head.getData(); head.setDate(null); size--; return e; }else{ SLNodel p = head; int i = 0; while (p.getNext() != null) { if (index-1 == i) { //前驱节点 E e = (E)p.getNext().getData(); p.setNext(p.getNext().getNext()); size--; return e; } else { p = p.getNext(); i++; } } } return null; } @Override public int indexOf(Object o) { SLNodel p = head; int index = 0; while (p.getNext()!=null){ if(p.getData().equals(o)){ return index; } p = p.getNext(); index++; } return -1; } @Override public int lastIndexOf(Object o) { SLNodel p = head; int index = size-1; while (p.getNext()!=null){ if(p.getData().equals(o)){ return index; } p = p.getNext(); index--; } return -1; } }
上面的代码是基于单链表实现的List接口,查询数据时要通过链表的头一直遍历到指定的位置获取数据效率较低,插入时因为不是数组所以不用考虑扩容的问题但是也需要从头遍历到指定位置插入,当然这里是可以优化的,我这里只是做了一最简单的实现而已。