数组(Array)是有限个相同类型的变量所组成的集合,数组中的每一个变量被称为元素,且每一个元素都有自己的下标,从0开始,到 array.length() -1 结束。
数组在内存中是顺序存储的,数组的每一个元素都存储在每一个存储单元中,并且元素元素之间紧密排列,既不打乱元素的存储顺序,也不跳过某个元素单元进行存储。
读取元素
随机读取,比如取array下标为n的数组,就可以直接拿array[n]。
/**
* 读取下标为2的元素,结果为5
*/
private static void readArray() {
int[] array = new int[] {7,0,5,2,2,2};
System.out.println(array[2]);
}
更新元素
只需将新值往数组的某一个元素位置塞入。
/**
* 将数组下标为3的元素替换为7
*/
private static void updateArray() {
int[] array = new int[] {7,0,5,2,2,2};
array[3] = 7;
System.out.println(array[3]);
}
插入元素
插入元素存在三种情况:尾部插入、中间插入、超范围插入,其中尾部插入和中间插入是在数组的实际元素数量小于数组长度的情况下进行的,下面一一来看。
尾部插入
尾部插入直接将要插入的元素直接放在数组尾部的空闲位置即可。
中间插入
因为每一个元素都有固定的下标,所以在中间插入的时候需要将要插入的位置和后面的元素向后移动,把地方腾出来,再把腾出来的那个位置插入元素。
/**
* 在指定位置插入元素
* @param index 插入的位置
* @param element 插入的元素
* @param size 数组实际元素数量
*/
private static void insert(int index,int element) throws Exception{
//判断是否超出范围
if(index < 0 || index >= size) {
throw new IndexOutOfBoundsException("out of array");
}
//从右向左循环查找到要插入的下标,把右边的元素逐个向右挪1位。
//i代表最后一个元素的下标,如果最后的下标大于要插入元素的下标,
//那么代表插入元素的位置在最后一个下标之前,
//所以,占了这个下标的元素和之后的元素都要向后移一位。
for(int i=size-1;i >= index; i--) {
array[index + 1] = array[i];
}
//腾出的位置放入新元素
array[index] = element;
//数组实际元素数量+1
size++;
}
超范围插入
超范围插入的意思就是现在有一个已经装满元素的数组了,现在还想往里面插入一个元素,该怎么办呢?
这就需要数组扩容了,但是数组的长度在创建时就已经确定了,所以可以创建一个新数组,再把旧数组的元素统统复制过去,这样就实现了数组的扩容。
/**
* 实现数组扩容
*/
public static void resize() {
int[] arrayNew = new int[array.length * 2];
//从旧数组复制到新数组中
//参数1:源数组
//参数2:源数组中拷贝元素的起始位置
//参数3:目标数组
//参数4:拷贝到目标数组的起始位置
//参数5:拷贝元素的个数
System.arraycopy(array, 0, arrayNew, 0, array.length);
}
扩容之后的数组,又可以使用中间插入的方式来插入元素了。
删除元素
删除元素的道理与插入元素大致相同,只是与插入元素反着来而已,插入元素是从右到左,一个一个挪位子给需要插入的元素腾出来位子;删除元素是从左到右,把要删除的元素右边的那些元素一个个的向左挪。
/**
* 数组删除元素
* @param index 删除的位置
* @param size 数组实际元素数量
*/
public static void delete(int index)throws Exception{
//判断是否超出范围
if(index < 0 || index >= size) {
throw new IndexOutOfBoundsException("out of array");
}
//从左到右循环,将元素逐个向左挪一位
for(int i=index;i < size-1; i++) {
array[i] = array[i+1];
}
//数组实际元素数量-1
size--;
}
总结
由于数组连续紧密的存储在内存中,只要给出下标,就能非常高效的随机访问能力;但插入删除元素需要后面的元素向左向右移动,严重的影响了效率。
所以,数组适合的场景是:读操作多、写操作少。