七:数组的定义与使用

1、数组的基本定义

          数组对于每一门编程语言来说都是重要的数据结构之一,当然不同语言对数组的实现及处理也不尽相同。Java 语言中提供的数组是用来存储固定大小的同类型元素。

          声明一个数组变量,如 numbers[100] 来代替直接声明 100 个独立变量 number0,number1,....,number99。

          数组的本质是一组相关变量的集合,但在Java里面将数组定义为了引用数据类型,所以数组的使用会和内存产生联系,而内存的关键字又与new相关。

          数组的定义格式:

类型格式特征
动态初始化

1)数组类型 数组名称  []   =  new   数据类型[长度]

2)数组类型  []   数组名称  =  new   数据类型[长度]

动态初始化之后数组每一个元素的保存内容为其对应数据类型的默认值
静态初始化简化格式

数据类型  数组名称  [] = {数据1,数据2,数据3,...} ;

数组定义的时候就为其设置好了里面的内容
完整格式数据类型  数组名称  [] =new 数据类型[]  {数据1,数据2,数据3,...} ;

          当创建了一个数组之后就可以按照如下的方式进行使用:

                    1)数组里面可以通过角标进行每一个元素的访问,脚标从0开始,而脚标范围是:0~数组长度-1;若脚标长度大于数组长度,则会出现数组越界异常;

                    2)使用数组是为了其可以进行方便的变量管理,所以在进行数组操作的时候会利用for循环来完成;

                    3)对于数组的长度也可以使用“数组名称.length”属性进行获得;

          范例:定义数组

 代码结果分析
动态化数组

package cn.demos;

public class Demo2 {

    public static void main(String arg[]) {
        // 使用数组动态初始化实现定义
        int data[] = new int[3];
        // 为数组设置内容
        data[0] = 1;
        data[1] = 2;
        data[2] = 3;
        for (int x = 0; x < data.length; x++) {
            // 输出当前数组的值
            System.out.println(data[x]);
        }
    }
}
 

1
2
3
动态初始化之后,数组之中的每一个元素的内容都是其对应数据类型的默认值,随后可以通过下标为数组进行内容的设置。
静态化数组

package cn.demos;

public class Demo2 {

    public static void main(String arg[]) {
        // 使用数组静态初始化
        int data[] = new int[]{11,22,33};
    
        for (int x = 0; x < data.length; x++) {
            // 输出当前数组的值
            System.out.println(data[x]);
        }
    }
}
 

11
22
33
在进行数组初始化的时候就进行赋值

2、数组的引用传递分析

          通过数组的基本定义可以发现,在数组使用的过程之中依然需要关键词new进行内存空间的开辟,所以数组也存在有内存引用的问题。

          范例:定义一个简单代码

package cn.demos;

public class Demo2 {

    public static void main(String arg[]) {
        // 使用数组静态初始化
        int data[] = new int[3];
        data[0] = 10;
        data[1] = 20;
        data[2] = 30;

        for (int x = 0; x < data.length; x++) {
            // 输出当前数组的值
            System.out.println(data[x]);
        }
    }
}
 

          针对上面的代码进行数组内存分析:

          但是数组本身属于引用数据类型,所以,会发生引用数据传递,按传统方式分析:一个堆内存可以被多个栈内存所指向。

          范例:观察数组引用

代码结果

package cn.demos;

public class Demo2 {

    public static void main(String arg[]) {
        // 静态初始化
        int data[] = new int[] { 10, 20, 30 };
        // 引用传递
        int temp[] = data;
        temp[0] = 99;
        for (int x = 0; x < data.length; x++) {
            System.out.println(data[x]);
        }
    }
}
 

99
20
30

          通过对上面程序进行内存分析,如下图:

          注意:数组属于引用类型,所以一定要为其开辟堆内存空间之后才可以使用,如果使用了未开辟堆内存空间的数组则一定会出现“NullPointerException”异常;且要先提供实例化对象才可以使用下标对数组进行操作。

 

3、foreach输出

          对于数组的输出,一般使用for循环实现。而传统的for循环在输出时采用的都是通过下标进行数组的输出。而为了避免在程序中操作不当出现数组越界异常,在JDK1.5之后,出现了增强版的for循环——foreach,利用foreach的语法结构可以直接自动获取数组中的每个元素,避免下标的访问。

 代码结果特点
for循环

package cn.demos;

public class Demo2 {

    public static void main(String arg[]) {
        // 静态初始化
        int data[] = new int[] { 1,2,3,4,5 };
        
        for (int x = 0; x < data.length; x++) {
            System.out.println(data[x]);
        }
    }
}
 

1
2
3
4
5
通过下标取数据
foreach语法

package cn.demos;

public class Demo2 {

    public static void main(String arg[]) {
        // 静态初始化
        int data[] = new int[] { 1, 2, 3, 4, 5 };

        for (int temp : data) {
            System.out.println(temp);
        }

    }
}
 

 可以自动将数组中的每一个元素的内容取出保存在变量里面,这样就可以直接通过变量获取数组内容,而非通过下标访问

for(数据类型  变量  :  数组  |  集合){}

 

4、二维数组

         传统的数据相当于一行数据,而二维数据则相当于行列式,即一维数组只需要通过一个下标就可以访问数组,而二维数组则需要通过两个下标进行数据访问(可根据表的结构进行类比,或者行列式)。

         二维数组定义语法:

分类定义
数组的动态初始化数组类型  数组名称 [][]  =  new  数据类型[行个数][列个数]
数组的静态初始化数据类型  数组名称[][]  = new  数据类型[][]  {{数据1},{数据2},...}

         范例:定义二维数组

代码结果

package cn.demos;

public class Demo2 {

    public static void main(String arg[]) {
        int data[][] = new int[][] { { 1, 2, 3, 4, 5 }, { 6, 7, 8, 9, 10 }, { 11, 12, 13, 14, 15 } };
        // 寻常输出
        for (int x = 0; x < data.length; x++) {
            for (int y = 0; y < data[x].length; y++) {
                System.out.println("data【" + x + "】【" + y + "】=" + data[x][y]);
            }
            System.out.println();
        }
        // 使用foreach输出
        for (int temp[] : data) {
            for (int num : temp) {
                System.out.print(num + "、");
            }
            System.out.println();
        }

    }
}
 

data【0】【0】=1
data【0】【1】=2
data【0】【2】=3
data【0】【3】=4
data【0】【4】=5

data【1】【0】=6
data【1】【1】=7
data【1】【2】=8
data【1】【3】=9
data【1】【4】=10

data【2】【0】=11
data【2】【1】=12
data【2】【2】=13
data【2】【3】=14
data【2】【4】=15

1、2、3、4、5、
6、7、8、9、10、
11、12、13、14、15、
 

          通过上面的程序代码,观察foreach的输出格式,可以得知二维数组就是数组的嵌套使用。

 

5、数组与方法

          对于引用数据类型而言,主要的特点是可以与方法进行引用传递,而数组也属于引用数据类型,所以,数组也可以通过方法实现引用传递的操作。

          范例:实现一个数组的引用传递

代码结果

package cn.demos;

public class Demo2 {

    public static void main(String arg[]) {
        int data[] = new int[] { 1, 2, 3, 4, 5 };
        // 传递数组
        printArray(data);
    }

    // 写一个打印方法;需要接收一个int型的数组
    public static void printArray(int temp[]) {
        for (int x = 0; x < temp.length; x++) {
            System.out.println(temp[x]);
        }
    }
}
 

1
2
3
4
5
 

          上述程序是定义一个方法接收数组类型的参数,所以,既然可以接收数组类型,那么就可以返回一个数组类型。

          范例:定义方法返回数组类型

代码结果

package cn.demos;

public class Demo2 {

    public static void main(String arg[]) {
        // 通过方法获得数组
        int data[] = initArray();
        // 传递数组
        printArray(data);
    }

    public static int[] initArray() {
        int arr[] = new int[] { 1, 2, 3, 4, 5 };
        return arr;
    }

    // 写一个打印方法;需要接收一个int型的数组
    public static void printArray(int temp[]) {
        for (int x = 0; x < temp.length; x++) {
            System.out.println(temp[x]);
        }
    }
}
 

1
2
3
4
5
 

          范例:通过方法修改内容

代码结果

package cn.demos;

public class Demo2 {

    public static void main(String arg[]) {
        // 通过方法获得数组
        int data[] = new int[] { 1, 2, 3, 4, 5 };
        // 修改数组内容
        changeArray(data);
        // 传递数组
        printArray(data);
    }

    public static void changeArray(int[] arr) {
        for (int x = 0; x < arr.length; x++) {
            // 每个元素的内容乘以2
            arr[x] *= 2;
        }
    }

    // 写一个打印方法;需要接收一个int型的数组
    public static void printArray(int temp[]) {
        for (int x = 0; x < temp.length; x++) {
            System.out.println(temp[x]);
        }
    }
}
 

2
4
6
8
10
 

          范例:定义一个数组,要求可以计算出这个数组元素的总和、最大值、最小值以及平均值。

代码结果

package cn.demos;

class ArrayUtil {
    private int sum;
    private double avg;
    private int max;
    private int min;

    public ArrayUtil(int data[]) {
        // 求最大值、最小值
        this.max = data[0];// 假设第一个为最大值
        this.min = data[0];// 假设第一个为最小值
        for (int x = 0; x < data.length; x++) {
            // if进行判断,假如数组里的值比max大,则进行交换
            if (data[x] > max) {
                this.max = data[x];
            }
            if (data[x] < min) {
                this.min = data[x];
            }
            this.sum += x;
        }
        this.avg = sum / data.length;
    }

    public int getSum() {
        return sum;
    }

    public void setSum(int sum) {
        this.sum = sum;
    }

    public double getAvg() {
        return avg;
    }

    public void setAvg(double avg) {
        this.avg = avg;
    }

    public int getMax() {
        return max;
    }

    public void setMax(int max) {
        this.max = max;
    }

    public int getMin() {
        return min;
    }

    public void setMin(int min) {
        this.min = min;
    }

}

public class Demo2 {

    public static void main(String arg[]) {
        // 通过方法获得数组
        int data[] = new int[] { 1, 2, 3, 4, 5 };
        ArrayUtil arrayUtil = new ArrayUtil(data);
        System.out.println("数组总和【" + arrayUtil.getSum() + "】");
        System.out.println("数组平均值【" + arrayUtil.getAvg() + "】");
        System.out.println("数组最大值【" + arrayUtil.getMax() + "】");
        System.out.println("数组最小值【" + arrayUtil.getMin() + "】");

    }

}
 

数组总和【10】
数组平均值【2.0】
数组最大值【5】
数组最小值【1】
 

 

6、数组排序案例分析

          数组排序指的是无序数组变成升序或降序排序。

          范例:按升序排序数组

代码结果

package cn.demos;

class ArrayUtil {
    public static void sort(int data[]) {
        // 进行数组排序处理
        for (int x = 0; x < data.length; x++) {
            for (int y = 0; y < data.length - x - 1; y++) {
                if (data[y] > data[y + 1]) {// 交换数据
                    int temp = data[y];
                    data[y] = data[y + 1];
                    data[y + 1] = temp;
                }
            }
        }
    }
}

public class Demo2 {

    public static void main(String arg[]) {

        int data[] = new int[] { 7, 9, 3, 4, 1, 8, 2, 5, 6 };
        ArrayUtil.sort(data);
        printArray(data);
    }

    public static void printArray(int temp[]) {
        for (int x = 0; x < temp.length; x++) {
            System.out.print(temp[x] + "、");
        }
        System.out.println();
    }

}
 

1、2、3、4、5、6、7、8、9、
 

7、数组转置案例分析

          数组的转置操作指的是前后转置处理,即:收尾交换。

          范例:数组转置

                    

转置前1,2,3,4,5,6,7,8
转置后8,7,6,5,4,3,2,1

          对于数组的转置,有两种思路,第一种则是定义一个新的数组,而后按照逆序的方式保存;第二种做法则是在一个数组上进行转置。

 代码结果
做法一

package cn.demos;

class ArrayUtil {
    public static void printArray(int temp[]) {
        for (int x = 0; x < temp.length; x++) {
            System.out.print(temp[x] + "、");
        }
        System.out.println();
    }
}

public class Demo2 {

    public static void main(String arg[]) {

        int data[] = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
        // 定义第二个数组
        int temp[] = new int[data.length];
        int foot = temp.length - 1;// 第二个数组的脚标
        for (int x = 0; x < data.length; x++) {
            temp[foot--] = data[x];
        }
        data = temp;
        ArrayUtil.printArray(data);
    }

}
 

8、7、6、5、4、3、2、1、
 
做法二

package cn.demos;

class ArrayUtil {
    public static void printArray(int temp[]) {
        for (int x = 0; x < temp.length; x++) {
            System.out.print(temp[x] + "、");
        }
        System.out.println();
    }
}

public class Demo2 {

    public static void main(String arg[]) {

        int data[] = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
        int center = data.length / 2;// 确定转换次数
        int head = 0;// 操作脚标
        int tail = data.length - 1;// 操作脚标
        for (int x = 0; x < center; x++) {
            int temp = data[head];
            data[head] = data[tail];
            data[tail] = temp;
            head++;
            tail--;
        }
        ArrayUtil.printArray(data);
    }

}
 

8、7、6、5、4、3、2、1、
 

          通过对上面两种做法的对比,可以发现第一种处理方式循环次数较多,且会产生垃圾;第二种的循环次数降低,具有if判断,增加了时间复杂度,但可以减少无用对象的产生。

 

8、数组相关类库

          1)数组排序:

数组排序java.util.Arrays.sort(数组)

          2)数组拷贝

数组拷贝system.arraycopy(源数组,源数组开始点,目标数组,目标数组开始点,拷贝长度)

          范例:实现数组拷贝

                    假设目前有两个数组:

数组一1,2,3,4,5,6,7,8
数组二11,22,33,44,55,66,77,88

                    拷贝之后的结果:

结果数组11,22,33,4,5,6,77,88
代码结构

package cn.demos;

class ArrayUtil {
    public static void printArray(int temp[]) {
        for (int x = 0; x < temp.length; x++) {
            System.out.print(temp[x] + "、");
        }
        System.out.println();
    }
}

public class Demo2 {

    public static void main(String arg[]) {

        int dataA[] = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
        int dataB[] = new int[] { 11, 22, 33, 44, 55, 66, 77, 88 };
        System.arraycopy(dataA, 3, dataB, 3, 3);
        ArrayUtil.printArray(dataB);
    }

}
 

11、22、33、4、5、6、77、88、
 

          这些操作都是系统本身提供的,即可在开发中直接使用。

 

9、方法可变参数

          范例:观察可变参数

代码结果

package cn.demos;

class ArrayUtil {
    public static int sum(int... data) {// 变相数组
        int sum = 0;
        for (int temp : data) {
            sum += temp;
        }
        return sum;
    }
}

public class Demo2 {

    public static void main(String arg[]) {
        System.out.println(ArrayUtil.sum(1, 2, 3));
        System.out.println(ArrayUtil.sum(new int[] { 2, 3, 4 }));
    }

}
 

6
9
 

          可变参数的最大作用在于,在以后进行一些程序类设计或者开发者调用时,利用可变参数就可以避免数组的传递操作,而可变参数的本质依然是数组。

10、对象数组

          在之前所接触的都是基本数据类型定义的数组,但是在Java程序本身各种数据类型都可以称为数组类型,所以类也可以成为数组类型,而这样的数组就称为对象数组。

          对象数组的定义格式:

 定义
静态初始化类  对象数组[]  =  new  类[]{实例化对象1,实例化对象2,...}
动态初始化类  对象数组[]  =  new  类[长度]

          范例:使用动态初始化

代码结果

package cn.demos;

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}

public class Demo2 {

    public static void main(String arg[]) {
        Person per[] = new Person[3];
        per[0] = new Person("张三", 13);
        per[1] = new Person("lisi", 14);
        per[2] = new Person("王五", 15);
        for (int x = 0; x < per.length; x++) {
            System.out.println(per[x]);
        }
    }

}
 

Person [name=张三, age=13]
Person [name=lisi, age=14]
Person [name=王五, age=15]
 

          范例:使用静态初始化

代码结果

package cn.demos;

class Person {
    private String name;
    private int age;

    public Person(String name, int age) {
        super();
        this.name = name;
        this.age = age;
    }

    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

}

public class Demo2 {

    public static void main(String arg[]) {
        Person per[] = new Person[] { 
                new Person("张三", 13), 
                new Person("lisi", 14), 
                new Person("王五", 15), };
        for (int x = 0; x < per.length; x++) {
            System.out.println(per[x]);
        }
    }

}
 

Person [name=张三, age=13]
Person [name=lisi, age=14]
Person [name=王五, age=15]
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值