zoukankan      html  css  js  c++  java
  • Java 集合系列03 ArrayList集合

    1. ArrayList定义

      ArrayList集合底层使用数组这种数据结构。ArrayList集合继承AbstractList集合,实现List,RandomAccess,Cloneable,java.io.Serializable接口。ArrayList集合是非线程安全的。

      ArrayList的构造函数:

    //默认构造函数,初始化容量为10
    //Constructs an empty list with an initial capacity of ten
    ArrayList()
    
    //初始化指定容量的构造函数
    ArrayList(int initialCapacity)
    
    //创建一个包含Collection的集合
    ArrayList(Collection<? extends E> collection)

    2. ArrayList集合的数据结构

    public class ArrayList<E> extends AbstractList<E>
            implements List<E>, RandomAccess, Cloneable, java.io.Serializable
    
        transient Object[] elementData;
        private int size;

      ArrayList集合包含两个重要的属性:elementData和size

      (1)elementData是一个Object类型的数组,保存添加到ArrayList集合中的元素。elementData是一个动态数组,可以通过ArrayList(int initialCapacity)指定初始化容量;如果使用不带参数的构造函数则默认初始化容量是10;elementData数组的大小也会根据ArrayList容量的增长而动态增长,具体增长方式是ensureCapacity()方法。

      (2)size属性是动态数组的大小;

    3. ArrayList扩容

      (1)使用无参数构造函数创建数组

    public class Test{
        public static void main(String[] args) {
            ArrayList list = new ArrayList();
            for (int i = 0; i < 10; i++) {
                list.add(i);
            }
            list.add(11);
        }
    }
        public boolean add(E e) {
            modCount++;
            add(e, elementData, size);
            return true;
        }
    
        private void add(E e, Object[] elementData, int s) {
            if (s == elementData.length)  //开始时,s == elementData.length
                elementData = grow();
            elementData[s] = e;
            size = s + 1;
        }
    
        private Object[] grow() {
            return grow(size + 1);
        }
    
        private Object[] grow(int minCapacity) {
            return elementData = Arrays.copyOf(elementData,
                                               newCapacity(minCapacity));  //newCapacity()扩容
        }
    
        private int newCapacity(int minCapacity) {
            // overflow-conscious code
            int oldCapacity = elementData.length;     //开始时,oldCapacity大小为0
            int newCapacity = oldCapacity + (oldCapacity >> 1);   //这时newCapacity也为0
            if (newCapacity - minCapacity <= 0) {
                if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA)
                    return Math.max(DEFAULT_CAPACITY, minCapacity);   //当添加第一个元素后,则设置数组大小为10
                if (minCapacity < 0) // overflow
                    throw new OutOfMemoryError();
                return minCapacity;
            }
            return (newCapacity - MAX_ARRAY_SIZE <= 0)
                ? newCapacity
                : hugeCapacity(minCapacity);
        }

    说明:

      第一种情况:使用无参数构造函数创建ArrayList时

      (1)在add第一个元素时,那么ArrayList的长度就会初始化为10;当之后在添加时只会调用elementData[s] = e,给数组的下一个元素赋值,不会在调用grow()进行扩容;

      (2)当数组的长度已经到10了,再次添加第11个元素时,则会再次进入grow()中进行扩容,新的容量大小是原来容量大小的1.5倍(newCapacity = oldCapacity + (oldCapacity >> 1)),即大小为15,并使用ArrayCopyof返回一个新的数组,新的数组中还未被使用的部分会默认使用null。

      (2)使用有参数构造函数创建数组

    public class Test{
        public static void main(String[] args) {
            ArrayList list = new ArrayList(5);
            for (int i = 0; i < 5; i++) {
                list.add(i);
            }
            list.add(6);
        }
    }
        public ArrayList(int initialCapacity) {
            if (initialCapacity > 0) {
                this.elementData = new Object[initialCapacity];
            } else if (initialCapacity == 0) {
                this.elementData = EMPTY_ELEMENTDATA;
            } else {
                throw new IllegalArgumentException("Illegal Capacity: "+
                                                   initialCapacity);
            }
        }
        private void add(E e, Object[] elementData, int s) {
            if (s == elementData.length)
                elementData = grow();
            elementData[s] = e;
            size = s + 1;
        }

    说明:

      第二种情况:使用有参数构造函数创建ArrayList时

      (1)会初始化指定大小的一个ArrayList然后直接给里面add元素;

      (2)当size == elementData.length时,会进入grow扩容,还无参数构造函数不一样的是不会进行初始化容量10的设置,会直接进行扩容原来容量的1.5倍后返回;

    4. ArrayList的遍历方式

      (1) 通过迭代器(iterator)遍历

            Collection c = new ArrayList();
            c.add("hello");
            c.add("world");
            c.add(100);
            c.add(new Person());
    
            Iterator it = c.iterator();
            while(it.hasNext()){
                Object obj = it.next();
                System.out.println(obj);
            }
        //如果需要再次遍历,需要重置迭代器
        /*Iterator it = c.iterator();
        while(it.hasNext()){
                Object obj = it.next();
                System.out.println(obj);
          }*/

      (2) 通过索引遍历

            ArrayList c = new ArrayList();
            c.add(1);
            c.add(2);
            c.add("hello");
            c.add(new Person());
    
            for(int i=0; i< c.size(); i++){
                Object ob = c.get(i);
                System.out.println(ob);
            }    

      (3) 通过for循环遍历

            ArrayList<Integer> al = new ArrayList();
            al.add(100);
            al.add(200);
            al.add(300);
    
            for(Integer i : al){             //增强for底层还是调用的迭代器Iterator()
                System.out.println(i);
            }    

    5. ArrayList常用API方法

    import java.util.ArrayList;
    import java.util.Collection;
    
    /*
        集合中可以保存所有类型的元素,集合中保存的都是元素的内存地址,引用
        集合中常用方法:
        1. add()   集合中添加元素
        2. size()   获取集合中元素的个数
        3. clear()   清除集合中的元素
        4. contains()  判断集合中是否包含指定的元素,返回布尔类型
        5. remove()   移除集合中的元素,返回布尔类型
        6. isEmpty()  判断集合是否为空,返回布尔类型
        7. toArray()  集合转换为Object类型的数组
     */
    public class CollectionTest01 {
        public static void main(String[] args) {
            Collection c = new ArrayList();     //多态,向下转型
            c.add(1);    //自动装箱,实际保存的是内存地址
            c.add(new Object());
            c.add(3.14);
            c.add("hello");
            c.add(new Person());
            System.out.println("集合中元素的个数:"+c.size());  //5
            c.clear();
            System.out.println("集合中元素的个数:"+c.size());   //0
            c.add("hello");
            c.add("world");
            c.add(1);
            c.add(new Object());
            c.add(true);
            System.out.println("集合中元素的个数:"+c.size());  //5
            boolean flag = c.contains("java");  //false
            System.out.println(flag);
            boolean flag1 = c.contains("hello");  //true
            System.out.println(flag1);
            boolean flag2 = c.remove(1);
            System.out.println(flag2);   //true
            System.out.println("集合中元素的个数:"+c.size());    //4
    
            boolean flag3 = c.isEmpty();
            System.out.println(flag3);
            c.clear();
            System.out.println(c.isEmpty());
    
            c.add("hello");
            c.add("world");
            c.add(100);
            c.add(new Person());
            Object[] obj = c.toArray();
            for (int i = 0; i < obj.length; i++) {
                System.out.println(obj[i]);
            }
        }
    }
    
    class Person{}

    6. 集合中contains方法和remove方法的使用

      集合中contains()方法,判断集合中是否包含指定的元素。

      contains()方法底层是equals()方法判断是否包含内容,不是比较的内存地址,equals()方法返回true则包含指定元素。

      集合中remove()方法,删除集合中的指定元素。

      remove()方法底层也是调用equals()方法,只要内容相同就可以删除指定元素。

    import java.util.ArrayList;
    import java.util.Collection;
    
    public class CollectionTest04 {
        public static void main(String[] args) {
            Collection c = new ArrayList();
            String s1 = new String("abd");
            String s2 = new String("bdc");
            c.add(s1);
            c.add(s2);
            System.out.println("元素的个数:"+c.size());
            String x = new String("abd");
            System.out.println(c.contains(x));  //true
    
            Collection cc = new ArrayList();
            String s3 = new String("hello");
            cc.add(s3);
            System.out.println("元素的个数:"+cc.size());  //1
            String s4 = new String("hello");
            cc.remove(s4);       //remove底层也是调用equals
            System.out.println("元素的个数:"+cc.size());   //0
        }
    }
  • 相关阅读:
    es6 简介
    npm 快速开发技巧
    css清除浮动方法
    mui 总结
    7种 JS 创建对象的经典方式
    JavaScript 的 this 原理
    使用定时器
    dom 操作及方法
    JavaScript的6种继承方式及其优缺点
    贪吃蛇游戏代码
  • 原文地址:https://www.cnblogs.com/homle/p/14631045.html
Copyright © 2011-2022 走看看