数组的定义和使用,理解多维数组和Array类

数组的作用

在执行程序的过程中,通常会需要存储大量数据。如果只有少量数据,那么通过声明变量,存储到变量中即可。但当我们的数据是20个、40个甚至是100以上时,就意味着需要声明很多变量,这是不现实的,不仅影响程序阅读,而且效率低下,不符合程序优化。这时就需要采用一个有条理并且高效的方法来存储大量数据。

数组是一种数据结构,可以用它来存储元素数量固定且元素类型相同的有序集。 若要存储100个int型的数据,可将它们存储到到一维数组中。 例如:int[] values = new int[100]; 一维数组和二维数组及多维数组的区别后续说明。

数组一旦创建,大小就固定,所以要注意元素数量是否大于数组长度。访问数组元素时,通过下标进行访问,数组第一位下标从0开始,所以数组最后一位下标,为数组长度-1。访问数组的第一位元素: values[0], 第二位元素:values[1] , 以此类推。

简单理解:数组是用于存储同类型数据的集合,而变量是存储单个数据。所以可以将数组看作一个存储相同类型的变量集合,将数组理解为一次性声明多个同类型的变量,并 统一管理。

定义一维数组

声明一维数组  elementType[] name; //元素类型[] 数组名

创建一维数组  new elementType[size]; //通过new操作符,创建指定类型和指定大小的数组。

注意:声明一个数组变量并不会在内存中开辟空间,它只是创建一个对数组引用的存储位置,用于指向数组的内存地址。如果数组变量未指向一个数组引用,则默认值为null,表示引用为空。 这里可以间接表明数组是一种对象类型(引用类型)。

通常情况下,声明数组和创建数组是一次完成,例如:String[] str = new String[10];  创建一个大小为10,String类型的数组,并将其数组引用赋给数组变量str。通常来讲,将str变量称为数组即可,它们的区别可以忽略。

此时str数组是没有元素的,给数组元素赋值:

1         String[] str = new String[10];
2         str[0] = "Java";     //第一位元素赋值
3         str[1] = "C++";     //第二位元素赋值
4         str[2] = "Python";  //第三位元素赋值
5         //.........依次类推,直到str[str.length-1]

 

如果已经知道数据,并且不多的情况,可以使用数组的初始化语法简化操作,两种方式都一样,推荐第一种。

        String[] str = {"Java","C++","Python"};
        String[] str = new String[]{"Java","C++","Python"};

注意:如果定义了数组,但未对数组元素进行初始化,那么数组元素会自动赋予默认值。 基本类型按照默认值规则,引用类型的默认值全部是null。

处理数组

当对数组元素进行操作,例如对数组某个下标的元素进行修改,或者遍历数组所有元素。通常都会使用for循环。
获取数组的几种遍历方式,for循环更加简洁。

 

//while遍历方式
int i = 0;
while(i<str.length){
    System.out.print(str[i] + " ");
    i++;
}
//for遍历方式
for(int i=0; i<str.length; i++){
    System.out.print(str[i] + " ");
}

除了通过下标遍历数组之外,java还有一个foreach循环,可以不通过下标来顺序地遍历数组。

for(String s : str){
    System.out.print(s + " ")
}

注意:foreach循环中对遍历的数组元素操作不会影响原来的数组元素,因为这里的s相当于形参。但如果我们想从指定位置遍历或修改某个数组元素时,则必须采用下标。

 

复制数组的操作和传递数组参数给方法

要复制数组元素可以使用三种方式:

  1. for循环或foreach遍历取值,赋值给另一个同类型长度相同的数组。
  2. 采用System.arraycopy() 方法。
  3. 使用clone()方法。
        //1.将数组元素复制给另一个数组
        for(int i = 0; i < arr.length; i++ ) {
            destArr[i] = arr[i];
        }
        
        //2.使用System.arraycopy()
        int[] copyArr = new int[arr.length * 2]; //建议目标数组长度增加2倍,可以容纳更多元素
        //参数说明:  源数组  要复制的元素起始位置  目标数组  复制的开始位置  复制的元素长度
        System.arraycopy(arr, 0, copyArr, 0, arr.length);
        int[] arr = {12,15,30,35};
//注意:数组变量是引用类型,这里是将arr指向的数组引用赋给assignArr,两者本质上是同一个数组 int[] assignArr = arr; assignArr[0] = 55; System.out.println(arr[0]); // 55 //3.采用clone(),相当于开辟一个新的内存空间 int[] cloneArr = arr.clone(); cloneArr[0] = 60; System.out.println(cloneArr[0]); //60 System.out.println(arr[0]); //50

 

将数组作为参数传递给方法

数组传递给方法和将参数值传递给方法是有很大不同的。Java是按值传递,所以传递基本类型数据时,传的是变量的值,所以对形参操作对实参不会产生影响。但传递数组则是传递该数组的引用地址,对该形参操作时,会影响实参。

    public static void main(String[] args) {
        int[] arr = {1,2,3};
        testArray(arr);
        System.out.println(Arrays.toString(arr)); //[2, 1, 3]
        testArray(arr[0], arr[1]);
        System.out.println(Arrays.toString(arr)); //[2, 1, 3]
    }
    //传递数组
    public static void testArray(int[] arr) {
        int temp = arr[0];
        arr[0] = arr[1];
        arr[1] = temp;
    }
    
    //传递数组元素
    public static void testArray(int a, int b) {
        int temp = a;
        a = b;
        b = temp;
    }

所以使用时,要注意区分传递的参数是基本数据类型还是引用类型。

二维数组

一维数组存储线性的元素集合,而二维数组可以存储矩阵和表格这种形式的数据。一维数组存储值,而二维存储的是一维数组的引用。三维数组中则存储的是二维数组,所以可以将多维看作“数组的数组”。二维数组中的元素通过两个下标来访问,这两个下标代表行和列。

定义一个二维数组,例如: int[][] test= new int[3][4]; //定义一个3行4列,int类型的二维数组。

二维第一个下标表示行,第二个下标表示列。行和列的下标都是从0开始,如图所示 :

    

        //二维数组元素初始化
        int[][] test = new int[3][4];
        test[0][0] = 1; //第一行第一列
        test[0][3] = 4; //第一行最后一列
        test[1][0] = 5; //第二行第一列
        test[1][3] = 8; //第二行最后一列
        //......
        //已知数据情况下,简便二维元素初始化操作
        int[][] test = {
                {1,2,3,4},
                {5,6,7,8},
                {9,10,11,13}};

可以很清楚地看到,每一行的数据都用一维数组来存储。二维访问元素时的[i][j],  [i]负责查找行(二维中的一维数组),[j]负责查找列(一维数组中的j下标元素)。

        test[0]; //指向二维中第一位一维数组元素
        test[1]; //指向二维中第二位一维数组元素
        test[2]; //指向二维中第三位一维数组元素

二维数组的长度就是其中存储的一维数组的数量。

如果只定义二维数组的长度,但没有定义一维的长度,赋值方式如下:

         //定义了二维长度,未定义其中的一维长度
        int[][] arr = new int[5][];
        System.out.println(arr[0]); //这时的二维数组元素相当于指向null
        
        arr[0] = new int[5];//为二维数组元素赋值
        arr[1] = new int[3];//为二维数组元素赋值
        arr[2] = new int[2];//为二维数组元素赋值
        //....

处理二维数组

关于处理数组的几种方式前面已经介绍了,这次采用for循环来遍历二维数组。

        //遍历二维数组
        for(int i = 0; i < arr.length; i++) {
            //这里是关键,访问arr[i],对arr[i]进行遍历,就是在遍历一维数组 
            for(int j = 0; j < arr[i].length; j++) {
                System.out.print(arr[i][j] + " ");
            }
        }

 

二维数组测试题

1.求某个二维数组中所有元素的和

View Code

2.对某个二维数组按列求和(矩阵形式,不然会导致索引越界)

View Code

3.求哪一列的和最大(能解决这个,就能解决哪一行的和最大问题)

View Code

若要练习更多二维数组的题目,可自行上网查阅。

三维数组

二维数组中存储一维数组,而一个三维数组则存储是二维数组。 三维数组的定义方式:

int[][][] arr = new int[3][3][2];

arr三维数组表示:能存放3个二维,二维中能存放3个一维,一维中能存放2个元素。

三维数组不常用, 这里只简单了解一下。例如存放30天中,每天的每个小时的湿度和温度。

可以用double[][][] weather = [30][24][2]; //建模思路: 湿度和温度可以用一维存放, 二维开辟24空间,一个一维表示当前小时的温度和湿度。三维开辟30空间,用于存放30天的天气。

[0][0][0] //获取第一天,1小时时候的湿度

[0][0][0] //获取第一天,1小时时候的温度

//....

[29][23][0] //获取第30天,24小时时候的湿度

[29][23][1] //获取第30天,24小时时候的温度

 

另外关于数组的排序,有多种排序方式,即可以自己实现,也可以调用Arrays工具类来进行排序。 

除了常规方式创建数组,简单了解通过反射来创建数组。
使用Array类的方法
static Object newInstance(Class<?> cla , int...dimension) 
根据传入的Class实例来声明类型,根据可变参数dimension来决定创建一维还是多维
static get(Object obj,int index)  : 获取指定对象数组中index值
static getXxx(Object obj,int index) : Xxx代表值类型,如果存储的是值类型,就使用该方式
static set(Object obj,int index)  : 设置指定对象数组中index值
static setXxx(Object obj,int index) : Xxx代表值类型,如果该对象数组是存储值类型,就使用该方式

//创建一个字符串类型的三维数组
Object arr = Array.newInstance(String.class,2,3,3); //2层3行3列
//获取该三维数组中的元素,得到二维数组
Object arr2 = Array.get(arr,0);  //arr2数组是一个二维数组
System.out.println(arr2); //输出arr,得到二维数组地址

如果要遍历该三维数组arr,必须强制转换成常规数组类型。

String[][][] strArr = (String[][][])arr;

需要注意点就是对象数组中储存的类型是值类型还是引用类型,然后根据不同类型去调用setXxx()或set()方法;

posted @ 2018-03-07 22:44  乘风起  阅读(2636)  评论(1编辑  收藏  举报