ArrayList顺序表

文章详细介绍了ArrayList的基本概念、内部原理,包括其作为线性表的特性,以及如何自我实现一个简单的顺序表。还探讨了ArrayList的扩容机制,并提供了具体的添加、删除、查找等操作示例。此外,提到了ArrayList在多线程环境中的线程不安全问题。

集合的概要

Java 集合框架 Java Collection Framework ,又被称为容器 container ,是定义在 java.util 包下的一组接口 interfaces和其实现类 classes
在这里插入图片描述

ArrayList集合原理

ArrayList是线性表,而线性表有:顺序表(ArrayList)、链表(LinkedList)、栈(Stack)、队列(Queue)…
顺序表:一般情况下采用数组存储,在数组上完成数据的增删查改。
在这里插入图片描述

ArrayList自我实现

我这里将框架给大家。大家可以自己实现一下。

public class SeqList {
private int[] array;
private int size;
// 默认构造方法
SeqList(){ 

}
// 将顺序表的底层容量设置为initcapacity
SeqList(int initcapacity){

}
// 新增元素,默认在数组最后新增
public void add(int data) {
 }
// 在 pos 位置新增元素
public void add(int pos, int data) {
 }
// 判定是否包含某个元素
public boolean contains(int toFind) { 
return true;
 }
// 查找某个元素对应的位置
public int indexOf(int toFind) {
 return -1;
  }
// 获取 pos 位置的元素
public int get(int pos) { 
return -1; 
}
// 给 pos 位置的元素设为 value
public void set(int pos, int value) { 
}
//删除第一次出现的关键字key
public void remove(int toRemove) {
 }
// 获取顺序表长度
public int size() { 
return 0; 
}
// 清空顺序表
public void clear() { 
}
// 打印顺序表,注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的
public void display() {
 }
}

我进行的ArrayList的数据结构

public class MyArraylist {

    public int[] elem;
    public int usedSize;//0
    //默认容量
    private static final int DEFAULT_SIZE = 10;

    public MyArraylist() {
        this.elem = new int[DEFAULT_SIZE];
    }

    /**
     * 打印顺序表:
     * 根据usedSize判断即可
     */
    public void display() {
        for (int i = 0; i < usedSize; i++) {
            System.out.println(elem[i]);
        }
    }

    // 新增元素,默认在数组最后新增
    public void add(int data) {
        if (isFull()) {
            Arrays.copyOf(elem, elem.length * 2);
        }

        elem[usedSize] = data;
        usedSize++;
    }

    /**
     * 判断当前的顺序表是不是满的!
     *
     * @return true:满   false代表空
     */
    public boolean isFull() {
        if (usedSize < elem.length) {
            return true;
        } else {
            return false;
        }
    }

    private boolean checkPosInAdd(int pos) {

        return true;//合法
    }

    // 在 pos 位置新增元素
    public void add(int pos, int data) {
        if (isFull()) {
            Arrays.copyOf(elem, elem.length * 2);
        }
        int tmp = 0;
        for (int i = pos + 1; i < usedSize; i++) {
            tmp = elem[i];
            elem[i] = elem[i - 1];
        }
        elem[usedSize] = tmp;
        usedSize++;
    }


    // 判定是否包含某个元素
    public boolean contains(int toFind) {
        for (int i = 0; i < usedSize; i++) {
            if (elem[i] == toFind) {
                return true;
            }
        }
        return false;
    }

    // 查找某个元素对应的位置
    public int indexOf(int toFind) {
        for (int i = 0; i < usedSize; i++) {
            if (elem[i] == toFind) {
                return i;
            }
        }
        return -1;
    }

    // 获取 pos 位置的元素
    public int get(int pos) throws RuntimeException {
        if (pos < 0 || pos > elem.length) {
            return -1;
        }
        //这里应该写抛出位置异常的,不过算了
        return elem[pos];
    }

    private boolean isEmpty() {
        if (usedSize == 0) {
            return true;
        }
        return false;
    }

    // 给 pos 位置的元素设为【更新为】 value
    public void set(int pos, int value) {
        if (pos < 0 || pos > elem.length) {
            return;
        }
        //这里应该写抛出位置异常的,不过算了
        elem[pos] = value;
    }

    /**
     * 删除第一次出现的关键字key
     *
     * @param key
     */
    public void remove(int key) {
        for (int i = 1; i < elem.length; i++) {
            if (key == elem[i]) {
                int tmp = elem[i];
                elem[i - 1] = elem[i];
            }
        }
        usedSize--;
    }

    // 获取顺序表长度
    public int size() {
        return elem.length;
    }

    // 清空顺序表
    public void clear() {
        usedSize = 0;
    }

ArrayList具体的操作

返回值方法解释
booleanadd(E e)尾插 e
voidadd(int index, E element)将 e 插入到 index 位置
booleanaddAll(Collection<? extends E> c)尾插 c 中的元素
Eremove(int index)删除 index 位置元素
booleanremove(Object o)删除遇到的第一个 o
Eget(int index)获取下标 index 位置元素
Eset(int index, E element)将下标 index 位置元素设置为 element
voidclear()清空
booleancontains(Object o)判断 o 是否在线性表中
intindexOf(Object o)返回第一个 o 所在下标
intlastIndexOf(Object o)返回最后一个 o 的下标
ListsubList(int fromIndex, int toIndex)截取部分 list

注意:
这里的E代表泛型,目前可以理解为所有类型都可以去填充容器(具体问题会在泛型的相关文章中体现)链接:

public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 0; i < 10; i++) {
            list.add(i+"");
}
// 获取list中有效元素个数
System.out.println(list.size());
// 获取和设置index位置上的元素,注意index必须介于[0, size)间
System.out.println(list.get(1));
list.set(1, "k");
// 在list的index位置插入指定元素,index及后续的元素统一往后搬移一个位置
list.add(2, "l");
// 删除指定元素,找到了就删除,该元素之后的元素统一往前搬移一个位置
list.remove("3");
// 删除list中index位置上的元素,注意index不要超过list中有效元素个数,否则会抛出下标越界异常
list.remove(list.size()-1);
// 检测list中是否包含指定元素,包含返回true,否则返回false
if(!list.contains("9")){
list.add("9");
}
}

ArrayList扩容机制

ArrayList关于容量扩容机制

在这里插入图片描述
源码总结:

  1. 检测是否真正需要扩容,如果是调用grow准备扩容
  2. 预估需要库容的大小
    1.初步预估按照1.5倍大小扩容
    2.如果用户所需大小超过预估1.5倍大小,则按照用户所需大小扩容
    3.真正扩容之前检测是否能扩容成功,防止太大导致扩容失败
  3. 使用copyOf进行扩容

小结

ArrayLIst太过于简单,操作数组,其实大家都会,我这里给大家说一些后面会用到的。

  1. ArrayList不是线程安全的,单线程可用
  2. 在多线程中可以选择Vector或者CopyOnWriteArrayList
  3. ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表

十一、其他文章接口

1.String方法(重要,对于操作字符串有巨大的帮助)

文章链接

2.java常用的接口及其方法(包含拷贝,比较,排序,构造器)

文章链接

3.初阶数据结构

3.1 顺序表:ArrayList

文章链接

3.2 链表:LinkedList

文章链接

3.3 栈:Stack

文章链接

3.4 队列:Queue

文章链接

3.5 二叉树:Tree

文章链接

3.6 优先级队列:PriorityQueue(堆排序)

文章链接

3.7 Map和Set

HashMap和HashSet,TreeMap和TreeSet
文章链接

4. 排序(7种方式)

4.1 插入排序(两种)

4.2 选择排序(两种)

4.3 快速排序

4.4 堆排序

里面有堆排序的实现和逻辑
文章链接

4.5 归并排序

5.多线程

文章链接

6.网络编程

7.HTML

8.数据库Mysql

文章链接

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值