集合框架-List(ArrayList、LinkedList)

196 阅读2分钟
  •  ArrayList
  • 查看了数据结构,简单的实现了一下ArrayList,主要注意的就是add  和 remove ,当然更多细节肯定没有做的,比如源码里有个关键字段modCount。。。

public void add(int index, T t) {
    checkIndex(index);
    //当数组满了就增加容量
    if (mItems.length == size()){
        ensureCapacity(size() * 2 + 1);
    }
    //然后进行插入操作
    for (int i = theSize; i > index ; i-- ) {
        mItems[i] = mItems[i - 1];
    }
    mItems[index] = t;
    theSize++;
}

public T remove(int index){
    checkIndex(index);
    Object mItem = mItems[index];
    //取出数据后在进行排列
    for (int i = index; i < size() - 1 ; i++) {
        mItems[i] = mItems[i + 1];
    }

    theSize -- ;
    return (T) mItem;
}
public T get(int indx){
    return (T) mItems[indx];
}

public T set(int inx , T t){
    if (inx < 0  || inx > theSize){
        throw  new IndexOutOfBoundsException();
    }
    Object mItem = mItems[inx];
    mItems[inx] = t;

    return (T) mItem;
}
    查看add  remove 就可以知道为什么增删会耗时了,因为增删操作会将后面的数据全部进行移动!
所以就增加的耗时的操作时间
    然而 get set 却 只是通过数组的下标来直接获取数值
  • LinkedList
  • 简单实现一下LinkedList,主要就是节点 Node  , 然后就是add(t) , addBefore (int ,t),get(int) 这3个方法的细节

//节点指针
private static class Node<T>{
    //指向上一个node
    private Node<T> prev;
    //指向下一个node
    private Node<T> next;
    //数据
    private T t;

    public Node(Node<T> prev, Node<T> next, T t) {
        this.prev = prev;
        this.next = next;
        this.t = t;
    }
}
//标记
private Node<T> startMarker;
private Node<T> endMarker;
/**
 * 添加数据到某条数据的前面
 */
public  void  add(T t){
    addBefore(size() , t);
}

public void addBefore(int index ,T t){

    if (index == size()){
        Node<T> newNode = new Node<>(endMarker.prev, endMarker, t);
        newNode.prev.next = newNode;
        endMarker.prev = newNode;

    }else {
        Node<T> node = node(index);
        Node<T> newNode = new Node<>(node.prev, node, t);
        newNode.prev.next = newNode;
        node.prev = newNode ;
    }

    theSize ++ ;
    modCount ++ ;
}/**
 * 移除某条数据
 */
public T remove(int index) {
    Node<T> p = node(index);
    return toRemove(p);
}

public T remove() {
    Node<T> prev = endMarker.prev;
    return toRemove(prev);
}

private T toRemove(Node<T> p) {
    p.prev.next = p.next;
    p.next.prev = p.prev;

    theSize--;
    modCount++;

    return p.t;
}/**
 * 通过下标 index 获取某条数据
 */
public T get(int index){
    return node(index).t;
}

/**
 *这里通过下标来进行 遍历 获取 下标对应的节点信息
 */
Node<T> node(int index){
    Node<T> node = null;

    //小于一半的size 就从开始的地方遍历 , 否则了就从尾部开始遍历 , 遍历完就是最后得到的数据
    if (index < size()/2 ){
        node = startMarker.next;
        for (int i = 0; i < index; i++) {
            node = node.next;
        }
    }else {
        node = endMarker.prev;
        for (int i = size()-1 ; i > index; i-- ) {
            node = node.prev;
        }
    }
    return node;
}

    其实 remove方法 和 add 方法很简单,只不过是吧当前数据对应节点的上一个、下一个的引用进行
更改就行,不需要在改动剩下的数据;
但是addBefore(index , t) 和 get(index) 、 remove(index)方法却需要通过 下标 来获取对应的节点,
这就需要通过node(index)方法来进行遍历的获取 ---> 这就是耗时操作的原因!!!

  • 这里附上LinkedList的add  remove图解

add

remove