首页 > 学院 > 开发设计 > 正文

数组(二):ArrayList的实现和Arrays类的使用

2019-11-10 17:59:01
字体:
来源:转载
供稿:网友

一、数组是否可以变长?

我们都知道,数组时定长的,初始化时一定要给定长度,由于这个长度的问题,我们在实际的开发中,会更倾向于使用容器,如ArrayList等,使用容器类时,无需考虑长度问题,因为容器已经帮我们处理了,那么数组就没有办法变长了吗?当然不是,ArrayList就是基于数组实现的,我们可以看看ArrayList是如何处理的

二、ArrayList的实现原理

ArrayList用一个Object数组作为其内部操作,并有一个成员变量size代表容器的长度

PRivate transient Object[] elementData; private int size;

添加数据时,调用add()方法:

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

调用add时,首先调用ensureCapacityInternal方法,该方法的目的是扩容,将数组的长度增加1

private void ensureCapacityInternal(int minCapacity) { modCount++; // overflow-conscious code if (minCapacity - elementData.length > 0) grow(minCapacity);}

而在ensureCapacityInternal中,首先判断扩容是否有溢出问题,没有溢出问题,就调用grow,进行扩容

private void grow(int minCapacity) { // 溢出处理 int oldCapacity = elementData.length; int newCapacity = oldCapacity + (oldCapacity >> 1); if (newCapacity - minCapacity < 0) newCapacity = minCapacity; if (newCapacity - MAX_ARRAY_SIZE > 0) newCapacity = hugeCapacity(minCapacity); // 扩容处理 elementData = Arrays.copyOf(elementData, newCapacity); }

这是扩容的核心代码,前面代码都是溢出处理,关键在于最后一句

elementData = Arrays.copyOf(elementData, newCapacity)

API文档的解释是:复制指定的数组,截取或用 null 或 0 填充(如有必要),以使副本具有指定的长度

也就是说,通过Arrays.copyOf,将数组elementData的长度扩大到newCapacity,扩大的部分填充由数组类型决定

例如:

int[] a = new int[]{1,2}; System.out.println("扩容前长度:" + a.length); a = Arrays.copyOf(a, 3); System.out.println("扩容后长度:" + a.length); System.out.println("填充的数据:" + a[2]);

输出: 扩容前长度:2 扩容后长度:3 填充的数据:0

三、Arrays类的使用

Arrays类包含用来操作数组(比如排序和搜索)的各种方法,这个类是必须熟练使用的! 该类的常用方法有:

方法 解释
asList(T… a) 返回一个受指定数组支持的固定大小的列表
copyOf(int[] original,int newLength) 复制指定的数组,填充的数据由数组类型决定,以使副本具有指定的长度
copyOfRange(long[] original, int from, int to) 将指定数组的指定范围复制到一个新数组
equals(int[] a, int[] a2) 如果两个指定的 int 型数组彼此相等,则返回 true
fill(int[] a, int val) 将指定的 int 值分配给指定 int 型数组的每个元素
sort(int[] a) 对指定的 int 型数组按数字升序进行排序
以上只用int类型数组做为example,同理其他类型数组同样的操作

四、数组的浅拷贝,copyOf的问题

当数组类型不是基本数据类型时,数组内存放的是对象的引用,因此在copyOf复制对象数组时,千万要注意,复制的对象的引用而不是对象本身!

class Person{ int age; public int getAge() { return age; } public void setAge(int age) { this.age = age; }}public class Array2 { public static void main(String[] args) { Person p = new Person(); p.setAge(20); Person[] a = new Person[]{p}; Person[] b = Arrays.copyOf(a, a.length); a[0].setAge(30); System.out.println("a的年龄:" + a[0].getAge()); System.out.println("b的年龄:" + b[0].getAge()); }}

输出: a的年龄:30 b的年龄:30

可以看见,a改变其值后,连b的值都改变了,这就是浅拷贝问题

有关于深浅拷贝的博文,参考: 渐析java的浅拷贝和深拷贝:http://www.cnblogs.com/chenssy/p/3308489.html。


上一篇:demo

下一篇:valgrind的使用

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表