自定义ArrayList

ArrayList

1、ArrayList底层是使用数据实现的存储(动态数组)

2、数组的特点:数组在内存中是一段连续的空间,每个元素都有一个下标,数组一旦创建,容量是不可以改变的。

3、根据下标的特性:查询效率较高,而增加和删除元素就会导致数据发生移动(创建新数组,将旧数组中数据拷贝到新数组中),大量的数据在增加或者删除就会很消耗性能

4、ArrayList是线程不安全的。

通过ArrayList源码分析

1、ArrayList的成员变量 elementData,是一个Object类型的数组

2、size:集合的个数

3、默认容量 DEFAULT_CAPACITY = 10 ;

自定义 ArrayList01

  • 构造方法:在不传值的情况下,默认数组的容量是10

  • 构造方法:在给一个容量的前提下,将容器赋给数组

  • 增加方法:将元素添加到数组中

  • toString方法:将集合中的元素进行遍历,循环打印每一个元素

package com.xw.arrayList;

/**
 * 自定义实现ArrayList
 */
public class MyArrayList01 {

    private Object[] elementData ;

    private int size ;

    private static final int DEFAULT_CAPACITY = 10 ;

    /**
     * 默认值10
     */
    public MyArrayList01(){
        elementData = new Object[10] ;
    }

    /**
     * 带容量的构造方法
     * @param capacity
     */
    public MyArrayList01(int capacity){
        elementData = new Object[capacity] ;
    }

    /**
     * 添加方法
     * @param object
     */
    public void add(Object object){
        elementData[size++] = object ;
    }

    public String toString(){
        StringBuilder sb = new StringBuilder() ;
        sb.append("[");
        for(int i=0;i<size;i++){
            sb.append(elementData[i]).append(",");
        }
        sb.append("]");
        int i = sb.lastIndexOf(",");
        if (i!=-1){
            sb.deleteCharAt(i);
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        MyArrayList01 myArrayList01 = new MyArrayList01(20);

        myArrayList01.add("abc");
        myArrayList01.add("efg");
        myArrayList01.add("hig");

        System.out.println(myArrayList01);
    }

}

自定义 ArrayList02

  • 在第一个的基础上添加泛型
package com.xw.arrayList;

/**
 * 添加泛型
 * @param <E>
 */
public class MyArrayList02<E> {

    private Object[] elementData ;
    private int size ;

    private static final int DEFAULT_CAPACITY = 10 ;

    public MyArrayList02(){
        elementData = new Object[10] ;
    }

    public MyArrayList02(int capacity){
        elementData = new Object[capacity] ;
    }

    /**
     * 添加方法
     * @param e
     */
    public void add(E e){
        elementData[size++] = e ;
    }

    public String toString(){
        StringBuilder sb = new StringBuilder() ;
        sb.append("[");
        for(int i=0;i<size;i++){
            sb.append(elementData[i]).append(",");
        }
        sb.append("]");
        int i = sb.lastIndexOf(",");
        if (i!=-1){
            sb.deleteCharAt(i);
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        MyArrayList02<String> myArrayList01 = new MyArrayList02<String>(20);

        myArrayList01.add("abc");
        myArrayList01.add("efg");
        myArrayList01.add("hig");

        System.out.println(myArrayList01);
    }
}

自定义 ArrayList03

思考问题:

1、数组的容量问题,在指定容量之后(20),循环添加操作(21)次,就会出现错误。-> 扩容问题

2、什么时候扩容?:在集合的 size==数组的长度

3、怎么扩容,扩多大:可以将新数组的长度 * /(+)操作,对于计算机底层来说,位运算效率是很高的 我们使用 >>(右移1位相当于除2取余) 或者 << (左移1位相当于*2)

4、其实扩容的本质就是创建新的数组,将旧数组中的数据拷贝到新数组中。

新增的方法

1、扩容

2、设置添加元素,根据指定下标添加元素

3、根据下标获取元素

4、增加一些判断操作

package com.xw.arrayList;

/**
 * 增加get set方法
 * @param <E>
 */
public class MyArrayList03<E> {

    private Object[] elementData ;
    // 长度
    private int size ;

    private static final int DEFAULT_CAPACITY = 10 ;

    public MyArrayList03(){
        elementData = new Object[10] ;
    }

    public MyArrayList03(int capacity){
        if (capacity<=0){
            throw new RuntimeException("容器容量不能为负数");
        }else if (capacity == 0){
            elementData = new Object[DEFAULT_CAPACITY];
        }else {
            elementData = new Object[capacity] ;
        }
    }

    /**
     * 添加方法
     * @param e
     */
    public void add(E e){
        // 什么时候扩容
        if (size==elementData.length){
            Object[] newArray = new Object[elementData.length+(elementData.length>>1)];
            System.arraycopy(elementData,0,newArray,0,elementData.length);
            elementData = newArray ;
        }
        elementData[size++] = e ;
    }

    /**
     * 获取元素
     * @param index
     */
    public <E> E get(int index){
        if (index<0||index>size-1){ // 10 index 0|0-9
            throw new RuntimeException("索引不合法");
        }
        return (E)elementData[index] ;
    }

    /**
     * 设置值
     * @param element
     * @param index
     */
    public void set(E element,int index){
        if (index<0||index>size-1){ // 10 index 0|0-9
            throw new RuntimeException("索引不合法");
        }
        elementData[index] = element ;
    }

    /**
     * toString
     * @return
     */
    public String toString(){
        StringBuilder sb = new StringBuilder() ;
        sb.append("[");
        for(int i=0;i<size;i++){
            sb.append(elementData[i]).append(",");
        }
        sb.append("]");
        int i = sb.lastIndexOf(",");
        if (i!=-1){
            sb.deleteCharAt(i);
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        MyArrayList03<String> myArrayList01 = new MyArrayList03<String>(20);

        for (int i = 0; i < 40; i++) {
            myArrayList01.add("xing"+i);
        }

        System.out.println(myArrayList01);
        System.out.println(myArrayList01.get(1).toString());

        myArrayList01.set("张三女",10);
        System.out.println(myArrayList01);

        myArrayList01.get(40);
        System.out.println(myArrayList01);
    }

}

自定义 ArrayList04

删除元素操作:

1、怎么删:本质还是数组的拷贝

 删除元素 -> 数组的拷贝
 a b c d e f index
 a b (c) d e f  index+1

2、如何拷贝:就是从删除掉的那个元素的下标+1的位置开始移动

  • elementData:原数组

  • index+1:从哪开始移动

  • elementData:新数组

  • index:新数组的下标开始移动的索引

  • elementMoved:移动多少

int elementMoved = elementData.length-1-index; // 计算个数
System.arraycopy(elementData,index+1,elementData,index,elementMoved);

3、最后一点:数组中最后一个位置空了出来,需要移除,集合的个数需要 --

4、增加的方法

  • 根据下标删除元素

  • 集合的个数

  • 判断是否为空

package com.xw.arrayList;

/**
 * 添加remove方法
 * size:获取集合的个数
 * isEmpty:判断集合是否为空
 * @param <E>
 */
public class MyArrayList04<E> {

    private Object[] elementData ;
    // 个数
    private int size ;

    private static final int DEFAULT_CAPACITY = 10 ;

    public MyArrayList04(){
        elementData = new Object[10] ;
    }

    public MyArrayList04(int capacity){
        if (capacity<=0){
            throw new RuntimeException("容器容量不能为负数");
        }else if (capacity == 0){
            elementData = new Object[DEFAULT_CAPACITY];
        }else {
            elementData = new Object[capacity] ;
        }
    }

    /**
     * 添加方法
     * @param e
     */
    public void add(E e){
        // 什么时候扩容
        if (size==elementData.length){
            Object[] newArray = new Object[elementData.length+(elementData.length>>1)];
            System.arraycopy(elementData,0,newArray,0,elementData.length);
            elementData = newArray ;
        }
        elementData[size++] = e ;
    }

    /**
     * 获取元素
     * @param index
     */
    public <E> E get(int index){
        if (index<0||index>size-1){ // 10 index 0|0-9
            throw new RuntimeException("索引不合法");
        }
        return (E)elementData[index] ;
    }

    /**
     * 设置值
     * @param element
     * @param index
     */
    public void set(E element,int index){
        if (index<0||index>size-1){ // 10 index 0|0-9
            throw new RuntimeException("索引不合法");
        }
        elementData[index] = element ;
    }

    /**
     * toString
     * @return
     */
    public String toString(){
        StringBuilder sb = new StringBuilder() ;
        sb.append("[");
        for(int i=0;i<size;i++){
            sb.append(elementData[i]).append(",");
        }
        sb.append("]");
        int i = sb.lastIndexOf(",");
        if (i!=-1){
            sb.deleteCharAt(i);
        }
        return sb.toString();
    }

    public void removeElement(E element){
        // 循环比较每一个元素
        for (int i=0;i<size;i++){
            if (element.equals(get(i))){
                remove(i);
            }
        }
    }

    public int size(){
        return size ;
    }

    public boolean isEmpty(){
        return size==0?true:false;
    }

    /**
     * 根据下标删除元素
     * @param index
     */
    public void remove(int index){
        // 删除元素 -> 数组的拷贝
        // a b c d e f index
        // a b d e f  index+1
        int elementMoved = elementData.length-1-index; // 5-2
        if (index>0){
            System.arraycopy(elementData,index+1,elementData,index,elementMoved);
        }
        // 移除最后一个元素
        elementData[size-1] = null ;
        size--;
    }

    public static void main(String[] args) {
        MyArrayList04<String> myArrayList01 = new MyArrayList04<String>(20);

        for (int i = 0; i < 40; i++) {
            myArrayList01.add("xing"+i);
        }

        System.out.println(myArrayList01);
        System.out.println(myArrayList01.get(1).toString());

        myArrayList01.set("张三女",10);
        System.out.println(myArrayList01);

        myArrayList01.remove(10);
        System.out.println(myArrayList01);

        System.out.println(myArrayList01.size());
        System.out.println(myArrayList01.isEmpty());

//        System.out.println(myArrayList01.size-1);
//        System.out.println(myArrayList01.elementData.length);
    }

}

OK !!!。

下一篇:自定义LinkedList

做的不好,多多指教
原文地址:https://www.cnblogs.com/xingStudy/p/14626825.html