java ArrayList 集合 特点 扩容

  1. 1.ArrayList可以通过构造⽅法在初始化的时候指定底层数组的⼤⼩

     通过⽆参构造⽅法的⽅式ArrayList()初始化,则赋值底层数Object[] elementData为⼀个默认空数组

     Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}所以数组容量为0,只有对数据进⾏添

     加add时,才分配默认DEFAULT_CAPACITY = 10的初始容量。

     他的⽆参构造器和有参构造器,⽆参就是默认⼤⼩,有参会判断参数

      

/**
     * Constructs an empty list with the specified initial capacity.
     *
     * @param  initialCapacity  the initial capacity of the list
     * @throws IllegalArgumentException if the specified initial capacity
     *         is negative
     */
    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);
        }
    }

    /**
     * Constructs an empty list with an initial capacity of ten.
     */
    public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
  1.  2.数组扩容实现

        假如我们现有一个数组默认长度10,现在需要新增一个元素,但是现在数组已经满了,怎么办呢
        1)他会重新定义一个长度为10+10/2的长度为15的数组
        2)把原数组拷贝到新数组在把指针指向地址改为新地址。

  1.  3.针对jdk1.7以后变化

        jdk1.7以前,new ArrayList();时候会调用this(10),默认容量是10,1.7以后默认是一个空数组,只有第一次add的时候容量才会改成10,也是为了性能的提高。

  1.  4.ArrayList的默认数组⼤⼩为什么是10?

        据说是因为sun的程序员对⼀系列⼴泛使⽤的程序代码进⾏了调研,结果就是10这个⻓度的数组是最常
        ⽤的最有效率的。也有说就是随便起的⼀个数字,8个12个都没什么区别,只是因为10这个数组⽐较的
        圆满⽽已哈哈。

  1.  5.ArrayList 增删很慢 
             /**
             * Appends the specified element to the end of this list.
             *
             * @param e element to be appended to this list
             * @return <tt>true</tt> (as specified by {@link Collection#add})
             */
            public boolean add(E e) {
                ensureCapacityInternal(size + 1);  
                elementData[size++] = e;
                return true;
            }

  1)在增加元素之前进行了校验ensureCapacityInternal,如果长度满了就扩容。
  在扩容时候jdk1.8以后进行了效率提升,采用了位运算,右移一位,其实就是除以2这个操作。
  然后就进行了数组拷贝。

/**
                 * Increases the capacity to ensure that it can hold at least the
                 * number of elements specified by the minimum capacity argument.
                 *
                 * @param minCapacity the desired minimum capacity
                 */
                private void grow(int minCapacity) {
                    // overflow-conscious code
                    int oldCapacity = elementData.length;
                    int newCapacity = oldCapacity + (oldCapacity >> 1);
                    if (newCapacity - minCapacity < 0)
                        newCapacity = minCapacity;
                    if (newCapacity - MAX_ARRAY_SIZE > 0)
                        newCapacity = hugeCapacity(minCapacity);
                    // minCapacity is usually close to size, so this is a win:
                    elementData = Arrays.copyOf(elementData, newCapacity);
                }

                 2)至于为什么说效率慢
                    ⽐如在一个长度为10的数组,我需要在index 5的位置去插入⼀个元素A。
                    那从代码⾥⾯我们可以看到,他复制了⼀个数组,是从index 5的位置开始的,然后把它放在了index
                    5+1的位置,给我们要新增的元素腾出了位置,然后在index的位置放⼊元素A就完成了新增的操作了,
                    如果这时候在遇到扩容就更慢了,删除也是类似方式操作。

  1.   6)ArrayList是线程安全的么?

        当然不是那样效率会更低,Vector是线程安全的

如果你不喜欢vector 也可以用Collections.synchronizedList把集合包起来,也可以达到想要的效果,其实原理和vector一样就是给所有的方法加上一层synchronized

List<String> list = Collections.synchronizedList(new ArrayList<String>());
list.add("1");
list.add("2");
list.add("3");

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ArrayList扩容原理是基于动态数组的机制。当ArrayList中的元素数量超过了当前容量时,它会创建一个新的数组,并将原来的元素复制到新数组中。新数组的容量通常是原数组容量的两倍。这样可以确保在添加新元素时不需要频繁地进行数组的扩容操作,提高了性能。 下面是一个简单的代码示例,展示了ArrayList扩容机制: ```java import java.util.ArrayList; public class ArrayListDemo { public static void main(String[] args) { ArrayList<Integer> list = new ArrayList<>(); for (int i = 0; i < 20; i++) { list.add(i); System.out.println("Size: " + list.size() + ", Capacity: " + getCapacity(list)); } } private static int getCapacity(ArrayList<?> list) { try { java.lang.reflect.Field field = ArrayList.class.getDeclaredField("elementData"); field.setAccessible(true); return ((Object[]) field.get(list)).length; } catch (Exception e) { e.printStackTrace(); return -1; } } } ``` 请注意,ArrayList扩容是自动进行的,并且你不需要显式地调用扩容方法。ArrayList会在需要时自动进行扩容,并在内部处理相关操作。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [Arraylist扩容机制原理是什么?](https://blog.csdn.net/Blue92120/article/details/130841825)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值