模拟实现ArrayList与 LinkedList

本文通过模拟实现ArrayList和LinkedList的基本操作,介绍了这两种数据结构的工作原理。包括数组的扩容、链表节点的添加与删除等核心功能。

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

可参考文章:ArrayList 与 LinkedList 底层实现分析

我们知道ArrayList 底层使用数组实现的,了解ArrayList 的实现原理之后,我们就可以通过代码去简单模拟实现其中的过程。

public class MyArrayList {

    Object [] elementDate = new Object[4];
    //数组中包含的非null 数据的大小
    public int size = 0;

    public void add(Object value){
        //当数组长度不够时进行扩容,长度为原数组非null 容量的两倍
        if(size >= elementDate.length){
            //完成数组的拷贝,实现扩容
            Object[] temp = new Object[size * 2];
            for(int i = 0; i< elementDate.length; i++)
                temp[i] = elementDate[i];
            elementDate = temp;
        }

        elementDate[size] = value;
        size ++;
    }

    //在操作集合时进行下标检查
    public void rangeCheck(int index){
        if(index >= size || index < 0)
            throw new IndexOutOfBoundsException("下标越界");
    }

    public Object get(int index){
        rangeCheck(index);
        return elementDate[index];
    }

    public void set(int index,Object value){
        rangeCheck(index);
        elementDate[index] = value;
    }


    public void clear(){
        //将数据清空,执行GC,释放内存,增加效率
        for (int i = 0; i < size; i++)
            elementDate[i] = null;

        size = 0;
    }

    public void remove(int index){
        rangeCheck(index);
        //以传入的下标为基准,将后面的所有数据向前移动一个单位
        for(int i=index; i<size; i++)
            elementDate[i] = elementDate[i+1];

        elementDate[size--] = null;
    }


    @Test
    public void testMyArrayList(){
        MyArrayList arrayList = new MyArrayList();
        for(int i=0; i<10; i++)
            arrayList.add(i);

        arrayList.remove(0);
        arrayList.set(0,100);
        for (int i=0; i<arrayList.size; i++)
            System.out.print(arrayList.get(i) + " ");

        System.out.println();

        arrayList.clear();
        System.out.println(arrayList.size);

    }
}

输出
100 2 3 4 5 6 7 8 9
0

通过单向链表模拟实现LinkedList,这里使用了单向链表简单实现了LinkedList 的一些方法。PS :LinkedList 底层使用了双向链表。


import org.junit.Test;

public class MyLinkedList {

    //头结点
    public Node head = null;
    //链表元素个数
    public int size = 0;

    public void add(Object value){
        Node node = new Node(value);

        if(head == null){
            head = node;
        }else{
            Node temp = head;
            while(temp.getNext() != null){
                temp = temp.getNext();
            }
            temp.setNext(node);
        }
        size ++;
    }

    //下标检查
    public void checkElementIndex(int index){
        if(index >= size || index < 0)
            throw new IndexOutOfBoundsException("下标越界");
    }

    public Object get(int index){
        checkElementIndex(index);

        //根据头结点找到当前节点,返回节点值
        Node temp = head;
        for(int i=0; i<index; i++){
            temp = temp.getNext();
        }
        return temp.getValue();
    }

    public void set(int index,Object value){
        checkElementIndex(index);

        //根据头结点找到当前节点,设置当前节点值
        Node temp = head;
        for(int i=0; i<index; i++){
            temp = temp.getNext();
        }

        temp.setValue(value);
    }

    //只需要让头结点为null 由于后续节点再无引用,会被GC 收集,因此效率很高
    public void clear(){
        head = null;
        size = 0;
    }

    public void remove(int index){
        checkElementIndex(index);

        //如果是头结点,让头结点变成头结点后的一个节点
        if(index == 0){
            head = head.getNext();
        }else{
            Node temp = head;
            //找到删除元素节点的前一个节点,改变其后继节点
            for(int i=0; i<index - 1; i++){
                temp = temp.getNext();
            }
            temp.setNext(temp.getNext().getNext());
        }

        size --;
    }

    //内部类,模拟单向链表,保存元素值与下一个节点
    private static class Node{
        private Object value;
        private Node next;

        Node(Object value){
            this.value = value;
        }

        public Object getValue() {
            return value;
        }
        public void setValue(Object value) {
            this.value = value;
        }
        public Node getNext() {
            return next;
        }
        public void setNext(Node next) {
            this.next = next;
        }
    }

    @Test
    public void testMyLinkedList(){
        MyLinkedList linkedList = new MyLinkedList();

        for(int i=0; i<10; i++)
            linkedList.add(i);

        linkedList.remove(0);
        linkedList.set(0,100);
        for (int i=0; i<linkedList.size; i++)
            System.out.print(linkedList.get(i) + " ");
        System.out.println();

        linkedList.clear();
        System.out.println(linkedList.size);
    }
}

输出
100 2 3 4 5 6 7 8 9
0

      这里只是运用其中的思想简单的模拟实现了ArrayList 与LinkedList ,源码中的ArrayList 与LinkedList 实现要比这复杂的多。如果小伙伴们有兴趣可以去查看底层的实现源码,想必一定会有收获。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值