欢迎访问昆山宝鼎软件有限公司网站! 设为首页 | 网站地图 | XML | RSS订阅 | 宝鼎邮箱 | 宝鼎售后问题提交 | 后台管理


新闻资讯

MENU

软件开发知识

必然造成内存空间的浪费 昆山软件开发 2、如果一次性扩容扩得不够

点击: 次  来源:宝鼎软件 时间:2017-07-30

原文出处: 五月的仓颉

媒介

这个分类中,将会写写Java中的荟萃。荟萃是Java中很是重要并且基本的内容,因为任何数据必不行少的就是该数据是如何存储的,荟萃的浸染就是以必然的方法组织、存储数据。这里写的荟萃,一部门是较量常见的、一部门是不常用可是我小我私家平时见到过的,一些较量相似的荟萃(好比HashMap和Hashtable)就只讲一个,突出它们之间的区别即可。

最后,要指出一点,对付荟萃,我认为存眷的点主要有四点:

1、是否答允空

2、是否答允反复数据

3、是否有序,有序的意思是读取数据的顺序和存放数据的顺序是否一致

4、是否线程安详 

ArrayList

ArrayList是最常见以及每个Java开拓者最熟悉的荟萃类了,顾名思义,ArrayList就是一个以数组形式实现的荟萃,以一张表格来看一下ArrayList内里有哪些根基的元素:

一定造成内存空间的挥霍 昆山软件开拓  2、假如一次性扩容扩得不足

四个存眷点在ArrayList上的谜底

今后每篇文章在讲授代码前,城市先对付一个荟萃存眷的四个点以表格形式做一个解答:

一定造成内存空间的挥霍 昆山软件开拓  2、假如一次性扩容扩得不足

添加元素

有这么一段代码:

public static void main(String[] args)
{
    List<String> list = new ArrayList<String>();
    list.add("000");
    list.add("111");
}

看下底层会做什么,进入add要领的源码来看一下:

 public boolean add(E e) {
     ensureCapacity(size + 1);  // Increments modCount!!
     elementData[size++] = e;
     return true;
}

先不去管第2行的ensureCapacity要领,这个要领是扩容用的,底层实际上在挪用add要领的时候只是给elementData的某个位置添加了一个数据罢了,用一张图暗示的话是这样的:

一定造成内存空间的挥霍 昆山软件开拓  2、假如一次性扩容扩得不足

多说一句,我这么绘图有必然的误导性。elementData中存储的应该是堆内存中元素的引用,而不是实际的元素,这么画给人一种感受就是说elementData数组内里存放的就是实际的元素,这是不太严谨的。不外这么画主要是为了利便起见,只要知道这个问题就好了。

扩容

我们看一下,结构ArrayList的时候,软件开发,默认的底层数组巨细是10:

public ArrayList() {
    this(10);
}

那么有一个问题来了,底层数组的巨细不足了怎么办?谜底就是扩容,这也就是为什么一直说ArrayList的底层是基于动态数组实现的原因,动态数组的意思就是指底层的数组巨细并不是牢靠的,而是按照添加的元素巨细举办一个判定,不足的话就动态扩容,扩容的代码就在ensureCapacity内里:

public void ensureCapacity(int minCapacity) {
modCount++;
int oldCapacity = elementData.length;
if (minCapacity > oldCapacity) {
    Object oldData[] = elementData;
    int newCapacity = (oldCapacity * 3)/2 + 1;
        if (newCapacity < minCapacity)
    newCapacity = minCapacity;
           // minCapacity is usually close to size, so this is a win:
           elementData = Arrays.copyOf(elementData, newCapacity);
}
}

看到扩容的时候把元素组巨细先乘以3,再除以2,最后加1。大概有些人要问为什么?我们可以想:

1、假如一次性扩容扩得太大,一定造成内存空间的挥霍

2、假如一次性扩容扩得不足,那么下一次扩容的操纵一定较量快地会到来,这会低落措施运行效率,要知道扩容照旧比价淹灭机能的一个操纵

所以扩容扩几多,是JDK开拓人员在时间、空间上做的一个衡量,提供出来的一个较量公道的数值。最后挪用到的是Arrays的copyOf要领,将元素组内里的内容复制到新的数组内里去:

public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
       T[] copy = ((Object)newType == (Object)Object[].class)
           ? (T[]) new Object[newLength]
           : (T[]) Array.newInstance(newType.getComponentType(), newLength);
       System.arraycopy(original, 0, copy, 0,
                        Math.min(original.length, newLength));
       return copy;
}

用一张图来暗示就是这样的:

一定造成内存空间的挥霍 昆山软件开拓  2、假如一次性扩容扩得不足

删除元素

接着我们看一下删除的操纵。ArrayList支持两种删除方法:

1、凭据下标删除

2、凭据元素删除,这会删除ArrayList中与指定要删除的元素匹配的第一个元素