List(ArrayList/LinkedList/Vector)总结

本文详细介绍了自定义ArrayList和LinkedList的实现,包括添加、删除、设置元素等操作,并对比了两者的区别。ArrayList基于数组,适合频繁访问,而LinkedList基于链表,适合频繁增删。同时,还探讨了Vector与ArrayList的区别,以及ArrayList和LinkedList在使用场景上的联系和差异。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ArrayList底层基于数组,数组在内存上是连续分配的地址空间,是对数组的升级,长度是动态的。

自定义ArrayList:

class MyArrayList<E>{
   private E[] elements;//存放元素的容器
   private int size; //实际的元素个数
    private final static int defaultCapacity = 5; //默认的初始化参数

    public MyArrayList(){
        this(defaultCapacity);
    }

    public MyArrayList(int capacity){
       elements = (E[])new Object[capacity];
    }

    public void add(E value){
        //判断是否需要扩容
        if(size == elements.length){
           //扩容
            this.elements = Arrays.copyOf(this.elements, 2*elements.length);
       }
        //插入元素到数组尾
        elements[size++] = value;
   }

    public boolean remove(E value){
        if(size == 0){
           return false;
       }
        for(int i=0; i<size; i++){
           if(value.equals(this.elements[i])){
               //i位置是所要删除的元素
                System.arraycopy(this.elements, i+1, this.elements, i, size-1-i);
              this.elements[--size] = null;
                return true;
            }
        }
        return false;
    }

    public boolean set(int index, E value){
        try{
            checkIndex(index);
            elements[index] = value;
            return true;
        } catch (UnsupportedOperationException e){
            System.out.println(e.getMessage());
           return false;
        }
    }

    public void checkIndex(int index){
        if(index < 0 || index >= elements.length){
            throw new UnsupportedOperationException("the index is illegal");
        }
    }

    public E get(int index){
      try{
           checkIndex(index);
           return elements[index];
       }catch (UnsupportedOperationException e){
            System.out.println(e.getMessage());
           return null;
       }
   }

   public boolean contains(E value){
        if(size == 0){
            return false;
       }
       for(int i=0; i<size; i++){
            if(this.elements[i].equals(value)){
                return true;
           }
        }
        return false;
    }

    public int size(){
        return this.size;
    }

   public boolean isEmpty(){
       return this.size == 0;
   }

    public String toString(){
       StringBuilder strs = new StringBuilder();
        for(int i=0; i<size; i++){
           strs.append(elements[i]+" ");
        }
       return strs.toString();
    }


public class TestDemo1 {
    public static void main(String[] args) {
        MyArrayList<String> list = new MyArrayList<>();
       list.add("1");
        list.add("2");
        list.add("3");
        list.add("4");
        list.add("5");
        list.add("6");
        list.add("7");

       System.out.println(list.toString());

        list.remove("6");
        list.remove("10");

        System.out.println(list.toString());

        list.set(0, "100");
       list.set(5, "tulun");
       System.out.println(list.toString());

      

       List<String> list1= new ArrayList<>();
        list1.add("123");
        list1.add("456");

       list1.remove("123");

      System.out.println(list1.size());
        String[] s  = (String[])list1.toArray();

       list1.set(0, "tulun");
    }
}

LinkedList底层基于双向链表实现,它和基于数组的list相比,在内存中空间是不连续的,可以作为list使用,也可以作为queue使用。

自定义LinkedList:

class MyLinkedList<E>{
    private int size; //链表的元素个数
    private Node<E> first; //指向链表的第一个元素
    private Node<E> last; //指向链表的最后一个元素

    class Node<E>{
        private E data;
        private Node<E> prev;
        private Node<E> next;

        public Node(E data, Node<E> prev, Node<E> next){
            this.data = data;
            this.prev = prev;
            this.next = next;
        }
    }

    public void add(E value){
        //尾插法
        //考虑链表为空和链表不为空两种情况
        Node<E> newNode = new Node<>(value, last, null);
        if(last == null){
            first = newNode;
        }else{
            last.next = newNode;
        }
        last = newNode;
        size++;
    }

    public void add(int index, E value){
        //确定index执行的节点
        if(index < 0 || index > size){
            return;
        }
        if(index == size){
            //尾插法
            add(value);
        }else{
            Node<E> succ = findNodeByIndex(index);
            Node<E> succPrev = succ.prev;
            Node<E> newNode = new Node(value, succPrev, succ);
            succ.prev = newNode;
            if(succPrev == null){
                //原先链表只有一个节点
                first = newNode;
            }else{
                succPrev.next = newNode;
            }
        }
    }

    public Node<E> findNodeByIndex(int index){
        Node<E> tmp = first;
        for(int i=0; i<index; i++){
            tmp = tmp.next;
        }
        return tmp;
    }

    public boolean remove(E value){
        //删除元素所在的节点
        Node<E> succ = findNodeByValue(value);
        if(succ == null){
            return false;
        }
        Node<E> succPrev = succ.prev;
        Node<E> succNext = succ.next;

        if(succPrev == null){
            //所要删除的是第一个节点
            first = succNext;
        }else{
            succPrev.next = succNext;
            succ.prev = null;
        }

        if(succNext == null){
            //所要删除的是最后一个节点
            last = succPrev;
        }else{
            succNext.prev = succPrev;
            succ.next = null;
        }
        succ.data = null;//方便垃圾回收
        size--;
        return true;
    }

    public Node<E> findNodeByValue(E value){
        //返回value所对应的第一个节点
        for(Node<E> tmp=first; tmp != null; tmp=tmp.next){
            if(value.equals(tmp.data)){
                return tmp;
            }
        }
        return null;
    }

    public E set(int index, E newValue){
        if(index < 0 || index >= size){
            return null;
        }
        Node<E> succ = findNodeByIndex(index);
        E oldValue = succ.data;
        succ.data = newValue;
        return oldValue;
    }

    public E get(int index){
        if(index < 0 || index >= size){
            return null;
        }
        return findNodeByIndex(index).data;
    }

    @Override
    public String toString(){
        StringBuilder strs = new StringBuilder();
        for(Node<E> tmp=first; tmp!=null; tmp=tmp.next){
            strs.append(tmp.data+" ");
        }
        return strs.toString();
    }
}
public class TestDemo4 {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(1);
        list.add(10);
        list.add(100);

        list.addLast(2);
        list.removeFirst();

        list.remove(1);

        System.out.println(list.get(1));

        list.set(1, 1000);

        for(Integer i: list){
            System.out.println(i);
        }

        Iterator<Integer> itr = list.iterator();
        while(itr.hasNext()){
            System.out.println(itr.next());
        }
   
}

Vector和ArrayList的区别和联系

相同点:Vector是在1.5之前使用的,集合框架库之后很少用。两者都是基于数组实现的,继承关系,实现的接口都是一样的。
区别:ArrayList1.5倍扩容,Vector2倍扩容.
构造函数稍微不同
线程安全不同,Vector是线程安全的
效率不同,Vector是同步的,所以效率会低于ArrayList。

LinkedList和ArrayList的区别和联系

区别:1.LinkedList底层是基于双向链表,ArrayList底层是基于数组实现的。
2.ArrayList访问效率高于LinkedList,因为数组访问效率高,双向链表还有前驱后驱指向,访问麻烦。
3.对于增删方法,LinkedList访问效率高于ArrayList,数组要一个一个按顺序删,而链表可以用指向直接断开链接。
联系ArrayList和LinkedList都是List接口的实现类,这两个类都是对List进行操作。List接口里定义了它们必须要实现的方法,比如add(E)、get(int)、remove(int)、set(E)等基本的List操作,然后这两个类就按照它们自己的方法来实现这些List的基本操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值