本文主要介绍用java数组来理解数据结构中的线性结构,对于数组的深入理解不做过多探讨,毕竟每门语言都有数组,同样数组也是最基础的,最典型的数据结构之一。
主要以Java代码形式展示说明。
目录
Java 数组
数组是最常见的一种数据结构,它是相同类型的用一个标识符封装到一起的基本类型数据序列或者对象序列。数组使用一个统一的数组名和不同的下标来唯一确定数组中的元素。实质上,数组是一个简单的线性序列,因此访问速度很快。
数组的基本使用
定义数组,获取数组长度
public static void main(String[] args) {
// 定义数组(创建数组)
int[] arr = new int[3];
// 获取数组长度
int arrLength = arr.length;
System.out.println(arrLength);
}
操作数组中的元素
public static void main(String[] args) {
// 定义数组(创建数组)
int[] arr = new int[3];
// 操作数组中的元素 (1、获取 2、赋值)
// 访问数组中的元素,一般采用 数组名[下标],且下标从0开始,最大可以取到长度-1
int one = arr[0];
System.out.println("获取数组中第一个元素:" + one);
// 为数组中的元素赋值
arr[0] = 99;
System.out.println("赋值之后的第一个元素:" + arr[0]);
}
遍历数组
public static void main(String[] args) {
// 定义数组(创建数组)
int[] arr = new int[3];
// 遍历数组(1、获取 2、赋值)
// 在遍历数组之前呢,给长度为3的数组赋满值
arr[0] = 99;
arr[1] = 98;
arr[2] = 97;
// 遍历数组其实就是遍历下标,因为他们都是有规范的,取值/下标 都是从0开始的
for (int i = 0; i < arr.length; i++) {
System.out.println("数组第" + i + "元素:" + arr[i]);
}
}
第二种赋值,在定义的时候赋值
public static void main(String[] args) {
// 创建数组的同时为数组中的元素赋值
int[] arr2 = {90, 80, 70, 60, 50};
System.out.println("第二种赋值方式,创建数组的时候同时赋值长度为:" + arr2.length);
System.out.println("第二种赋值方式,创建数组的时候同时赋值内容为:" + Arrays.toString(arr2));
}
运行结果:
数组元素的添加
解决数组的长度不可变的问题
public static void main(String[] args) {
// 解决数组的长度不可变的问题
int[] arr = new int[]{9, 8, 7};
// 快速查看数组中的元素
System.out.println(Arrays.toString(arr));
// 要加入数组的目标元素
int addNum = 6;
//------------------操作步骤
// 创建一个新的数组,长度是原数组长度+1
int[] newArr = new int[arr.length + 1];
// 把 原数组的数据全部复制到新数组中
for (int i = 0; i < arr.length; i++) {
newArr[i] = arr[i];
}
// 把 目标元素放入新数组的最后
newArr[arr.length] = addNum;
// 把新数组替换原数组
arr = newArr;
System.out.println(Arrays.toString(arr));
}
运行结果:
数组元素的删除
删除数组中元素为3的数据,也就是删除下标为2的数据
/**
* 如何删除数组中的元素
*
* @param args
* @return void
* @author Soinice
* @date 2019/4/17 22:51
*/
public static void main(String[] args) {
// 目标数组
int[] target = new int[]{1, 2, 3, 4, 5};
System.out.println(Arrays.toString(target));
// 要删除的元素为:3,下标为:2
int delNum = 2;
//------------------操作步骤
// 创建一个新的数组,长度是原数组的长度-1
int[] newArr = new int[target.length - 1];
// 复制原数组中除了要删除的那个元素以外,其他的元素
for (int i = 0; i < newArr.length; i++) {
// 分为两种情况处理
// 1.当前遍历的下标小于要删除元素的下标
// 要删除的元素之前的下标
if (i < delNum) {
newArr[i] = target[i];
} else {
// 2.除去3的元素,后面的元素也保持不变的继续添加
// 要删除的元素之后的下标
newArr[i] = target[i + 1];
}
}
// 新数组替换旧数组
target = newArr;
System.out.println(Arrays.toString(target));
}
运行结果:
面向对象的数组
面向对象:
把数据以及对数据的操作方法放在一起,作为一个相互依存的整体。而这个整体就可以叫做 对象;
定义一个可以存储数据以及对数据的操作方法的对象
package array;
import java.util.Arrays;
/**
* 面向对象的数组
*
* @author Soinice
* @date 2019/4/18 21:48
*/
public class ArrayObject {
/**
* 用于存储数据的数组
*/
private int[] array;
public ArrayObject() {
this.array = new int[0];
}
/**
* 获取数组长度的方法
*
* @param
* @return int
* @author Soinice
* @date 2019/4/18 21:51
*/
public int size() {
return array.length;
}
/**
* 往数组的末尾添加一个元素
*
* @param num
* @return void
* @author Soinice
* @date 2019/4/18 22:06
*/
public void add(int num) {
// 创建一个新的数组
int[] newArr = new int[array.length + 1];
// 把原数组中的元素复制到新数组中
for (int i = 0; i < array.length; i++) {
newArr[i] = array[i];
}
// 把添加的元素放入新数组中
newArr[array.length] = num;
// 新数组替换旧数组
array = newArr;
}
/**
* 打印所有元素到控制台
*
* @param
* @return void
* @author Soinice
* @date 2019/4/18 22:06
*/
public void show() {
System.out.println("数组中的元素:" + Arrays.toString(array));
}
/**
* 删除数组中的元素
*
* @param index 下标索引
* @return void
* @author Soinice
* @date 2019/4/18 22:12
*/
public void del(int index) {
arrayIndexOutOfBoundsException(index);
//--------------------开始删除数组内容
// 创建一个新的数组,长度为原数组的长度-1
int[] newArr = new int[array.length - 1];
// 复制原有数据到新数组
for (int i = 0; i < newArr.length; i++) {
// 想要删除的元素前面的元素
if (i < index) {
newArr[i] = array[i];
} else {
// 想要删除的元素后面的元素
newArr[i] = array[i + 1];
}
}
// 新数组替换旧数组
array = newArr;
}
/**
* 获取某个元素
*
* @param index 下标索引
* @return int
* @author Soinice
* @date 2019/4/18 22:22
*/
public int get(int index) {
arrayIndexOutOfBoundsException(index);
return array[index];
}
/**
* 插入一个元素到指定位置
*
* @param index 指定位置
* @param num 某一个元素
* @return void
* @author Soinice
* @date 2019/4/18 22:26
*/
public void insert(int index, int num) {
// 创建一个新数组
int[] newArray = new int[array.length + 1];
// 将原有数组中的元素放入新数组中
for (int i = 0; i < array.length; i++) {
// 目标位置之前的元素
if (i < index) {
newArray[i] = array[i];
} else {
// 目标位置之后的元素
newArray[i + 1] = array[i];
}
}
// 插入新元素
newArray[index] = num;
// 新数组替换旧数组
array = newArray;
}
/**
* 替换指定位置的元素
*
* @param index
* @param num
* @return void
* @author Soinice
* @date 2019/4/18 22:38
*/
public void set(int index, int num) {
arrayIndexOutOfBoundsException(index);
array[index] = num;
}
/**
* 数组索引超出界限异常
*
* @param
* @return void
* @author Soinice
* @date 2019/4/18 22:45
*/
private void arrayIndexOutOfBoundsException(int index) {
// 判断下标是否越界
if (index < 0 || index > array.length - 1) {
throw new RuntimeException("下标越界");
}
}
}
定义一个操作的主对象
package array;
/**
* 面向对象的数组
*
* @author Soinice
* @date 2019/4/18 21:52
*/
public class MyArrayObject {
public static void main(String[] args) {
// 创建一个可变的数组
ArrayObject arrayObject = new ArrayObject();
// 获取长度
int size = arrayObject.size();
System.out.println("原数组长度:" + size);
arrayObject.show();
// 往可变数组中添加一个元素
arrayObject.add(1);
arrayObject.add(2);
arrayObject.add(3);
System.out.println("添加一个元素后数组的长度:" + arrayObject.size());
// 打印可变数组中的元素
arrayObject.show();
// 删除某个元素
arrayObject.del(1);
arrayObject.show();
System.out.println("删除某个元素后的数组长度:" + arrayObject.size());
// 获取某个元素
System.out.println("获取第1个元素,下标为0: " + arrayObject.get(0));
// 插入某元素到指定位置
System.out.println("*****************************");
arrayObject.add(4);
arrayObject.add(5);
arrayObject.show();
// 插入元素为2的数字到数组中第2个位置(下标为1)
System.out.println("插入元素为2的数字到数组中第2个位置");
arrayObject.insert(1, 2);
arrayObject.show();
// 替换某元素到指定位置
System.out.println("*****************************");
arrayObject.set(2, 333);
arrayObject.show();
System.out.println("替换第3个位置为333后的长度:" + arrayObject.size());
}
}
运行结果:
总结
数组的特殊性
(一)数组标识符是一个引用,指向堆中创建的一个真实对象,而这个(数组)对象保存了指向其他对象的引用。
(二)如果数组中保存的数据是引用类型时,实际是保存的对象引用,而保存的数据是基本数据类型是,实际是保存的基本数据的值。
(三)数组的length只表示数组能够容纳多少元素,也就是说,length是数组的大小,而不是实际保存的元素个数。
(四)多维数组可以使用Arrays.deepToString()将多维数组转换成String。
(五)不能使用泛型创建数组
T []list=new T[size]; //会报错
解决方法:
使用Object转型:
Object [] objs=new Object[size];
T []Objs=(T[])objs;
数组为什么特殊
Java中有大量其他的方式可以持有对象,那么,到底是什么使数组变得与众不同呢?
数组与其他种类的容器之间的区别有三个方面:效率、类型和保存基本类型的能力。在Java中,数组是一种效率最高的存储和随机访问对象引用序列的方式。数组就是一个简单的线性序列,这使得元素访问非常快速。但是为这种速度所付出的代价是数组对象的大小被固定,并且在其生命周期中不可改变。你可能会建议使用ArrayList,它可以通过创建一个新实例,然后把旧实例中所有的引用移到新实例中,从而实现更多空间的自动分配。尽管通常应该首选ArrayList而不是数组,但是这种弹性需要开销,因此ArrayList的效率比数组低很多。
数组和容器都可以保证你不能滥用它们。无论你是使用数组还是容器,如果越界,都会得到一个表示程序员错误的RuntimeException异常。
数组是第一级对象
无论使用哪种类型的数组,数组标识符其实只是一个引用,指向在堆中创建的一个真实对象,这个(数组)对象用以保存指向其他对象的引用。可以作为数组初始化语法的一部分隐式地创建次对象,或者用new表达式显示地创建。只读成员length是数组对象的一部分(事实上,这是唯一一个可以访问的字段或方法),表示此数组可以存储多少元素。“[]”语法是访问数组对象唯一的方式。
数组的初始化
新生成一个数组对象时,其中所有的引用被自动初始化为null;所以检查其中的引用是否为null,即可知道数组的某个位置是否存有存项。同样基本类型的数组如果是数值型的,就被自动初始化为0;如果是字符型(char)的,就被自动初始化为(char)0;如果是布尔型(boolean),就被自动初始化为false。
参考文献
相关文献: