数组:指的就是一组相关类型的变量集合,并且这些变量可以按照统一的方式进行操作。

1.数组的基本概念

1.1.数组的动态初始化

1.1.1.数组的开辟

数组的动态初始化要声明开辟数组,语法格式如下:

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

1.1.2.对数组的操作

  • 数组的访问通过索引完成。即“数组名称[索引]”,要注意的是,数组索引从0开始,因此可以采用的索引范围就是0~数组长度-1。如果超出索引可访问区间就会产生“java.lang.ArrayIndexOutOfBoundsException”异常消息
  • 当数组采用动态初始化开辟空间后,数组之中的每个元素都是都是该数据类型的默认值
  • 数组本身是一个有序的集合操作,所以对于数组的内容操作往往是采用循环的模式完成(因为数组是一个有限集合,所以一般采用for循环)
  • Java中动态取得数组长度的方法:数组名称.length

示例如下:

public class Test{
    public static void main(String[] args) {
        //开辟一个长度为3的整型数组
        int[] x = new int[3];
        System.out.println(x.length);
        //对数组进行实例化
        x[0] = 1;
        x[1] = 3;
        x[2] = 5;
        for (int i = 0; i < x.length; i++) {
            //通过循环控制索引访问数组元素
            System.out.println(x[i]);
        }
    }
}
//输出
//3
//1
//3
//5

数组本身除了声明并开辟空间意外还有另一种开辟模式:分布进行数组实例化,示例如下

int[] x = null;
x = new int[3];

!!!!!注意:数组属于引用数据类型,因此在使用前一定要开辟空间(进行实例化),否则就会出现“NullPointerException

1.2.数据引用传递

首先我们通过如下程序了解一下数组的空间开辟:

public class Test{
    public static void main(String[] args) {
        int[] x = null;
        x = new int[3];
        System.out.println(x.length);
        //给数组放入值
        x[0] = 1;
        x[1] = 3;
        x[2] = 5;
        for (int i = 0; i < x.length; i++) {
            //通过循环控制索引访问数组元素
            System.out.println(x[i]);
        }
    }
}

Java 查找数组中的索引_Java 查找数组中的索引


数组作为引用数据类型,也可以发生一定的引用传递。所谓引用传递空间就是指同一块内存空间可以被不同的栈内存所指向,示例如下:

public class Test{
    public static void main(String[] args) {
        int[] x = null;
        int[] temp = null;
        x = new int[3];
        //System.out.println(x.length);
        x[0] = 1;
        x[1] = 3;
        x[2] = 5;
        //如果要出现引用传递,不要出现[]
        temp = x;
        //修改数据
        temp[0] = 99;
        System.out.println(x[0]);//99
    }
}

Java 查找数组中的索引_数组与方法互操作_02

1.3.数组的静态初始化

数组动态初始化:数组首先先开辟内存空间,而后再使用索引进行内容的设置 数组静态初始化:数组在定义的同时可以设置内容,数组的静态初始化方法有两种:

  • 简化格式
数据类型[] 数组名称 = {值1,值2.....值n};
  • 完整格式(推荐
数据类型[] 数组名称 = new 数据类型[]{值1,值2.....值n};

静态初始化数组示例代码如下:

public class Test{
    public static void main(String[] args) {
        int[] x = new int[]{1,2,5,55};
        System.out.println(x.length);
        for (int i = 0; i < x.length; i++) {
            System.out.println(x[i]);
        }
    }
}
//输出
//4
//1
//2
//5
//55

在开发中,对于静态数组一般推荐使用完整格式,这样可以便于使用匿名数组,示例如下:

public class Test{
    public static void main(String[] args) {
        System.out.println(new int[]{1,23,4,5,543}.length);
    }
}
//输出
//5

数组的最大缺陷:长度固定(存在越界问题)

2.二维数组

二维数组有如下两种声明格式

  • 动态初始化
数组类型[][] 数组名 = new 数组类型[行数][列数];
  • 静态初始化
数组类型[][] 数组名 = new 数组类型[][]{{值1,值2.....值n},{值1,值2.....值n}....{值1,值2.....值n}};

数组的数组就是二维数组,定义一个二维数组示例如下:

public class Test{
    public static void main(String[] args) {
        //数组并不是等列数组
        int[][] data = new int[][]{
                {1,2,3},{4,5},{6,7,8,9}
        };
        //在进行输出时要使用双循环
        for (int i = 0; i < data.length; i++) {
            for (int j = 0; j < data[i].length; j++) {
                System.out.println("data["+i+"]["+j+"]="+data[i][j]);
            }
        }
    }
}
//输出
//data[0][0]=1
//data[0][1]=2
//data[0][2]=3
//data[1][0]=4
//data[1][1]=5
//data[2][0]=6
//data[2][1]=7
//data[2][2]=8
//data[2][3]=9

3.数组与方法互操作

数组是引用数据类型,所有引用数据类型都可以为其设置多个栈内存指向,所以在进行数组操作的时候,也可以通过方法进行处理

3.1.方法接收数据

示例代码如下:

public class Test{
    public static void main(String[] args) {
        int[] data = new int[]{1,2,3,4};
        printArray(data);
    }
    public static void printArray(int[] data){
        for (int i = 0; i < data.length; i++) {
            System.out.println(data[i]);
        }
    }
}
//1
//2
//3
//4

3.2.方法返回数组

示例代码如下:

public class Test{
    public static void main(String[] args) {
        int[] data = init();
        printArray(data);
    }
    //定义一个数组返回方法
    public static int[] init(){
        return new int[]{1,2,3,4};
    }
    //定义一个数组打印方法
    public static void printArray(int[] data){
        for (int i = 0; i < data.length; i++) {
            System.out.println(data[i]);
        }
    }
}
//1
//2
//3
//4

3.3.方法修改数组

现在的数组上发生了引用传递,那么久意味着方法在接收数组后也可以修改数组,方法修改数组示例代码如下:

public class Test{
    public static void main(String[] args) {
        int[] data = init();
        bigger(data);
        printArray(data);
    }
    //定义一个数组返回方法
    public static int[] init(){
        return new int[]{1,2,3,4};
    }
    //定义一个数组打印方法
    public static void printArray(int[] data){
        for (int i = 0; i < data.length; i++) {
            System.out.println(data[i]);
        }
    }
    //定义方法将数组中每个值扩大5倍
    public static void bigger(int[] data){
        for (int i = 0; i < data.length; i++) {
            data[i] = data[i] * 5;
        }
    }
}
//5
//10
//15
//20

4.Java对数组的支持

4.1.排序

在JavaSE给出的类库中也提供有对数组的支持

  • 数组排序:java.util.Arrays.sort(数组名称);

实现数组排序操作示例代码如下:

public class Test{
    public static void main(String[] args) {
        int[] intData = new int[]{1,62,31,24};
        char[] charData = new char[]{'a','z','b','d'};
        java.util.Arrays.sort(intData);
        java.util.Arrays.sort(charData);
        printArray(intData);
        printArray(charData);
    }
    public static void printArray(int[] data){
        for (int i = 0; i < data.length; i++) {
            System.out.println(data[i]);
        }
    }
    //方法重载
    public static void printArray(char[] data){
        for (int i = 0; i < data.length; i++) {
            System.out.println(data[i]);
        }
    }
}
//1
//24
//31
//62
//a
//b
//d
//z

只要是基本数据类型的数组,sort方法都可以进行排序处理(默认升序处理),其内部使用双轴快速排序。

4.2.数组部分拷贝

数组部分拷贝:指的是将一个数组的部分内容替换掉另一个数组的部分内容(必须是连续的

4.2.1.拷贝数组指定部分到指定位置

方法如下:

System.arraycopy(源数组名称,源数组开始点,目标数组名称,目标数组开始点,拷贝长度);

目标数组A:1,2,3,4,5,6,7,8,9
源数组B:11,22,33,44,55,66,77,88,99
替换后:1,55,66,77,5,6,7,8,9
示例代码如下:

public class Test{
    public static void main(String[] args){
        int[] dataA = new int[]{1,2,3,4,5,6,7,8,9};
        int[] dataB = new int[]{11,22,33,44,55,66,77,88,99};
        System.arraycopy(dataB,4,dataA,1,3);
        printArray(dataA);
    }
    public static void printArray(int[] data){
        for (int i = 0; i < data.length; i++) {
            System.out.println(data[i]);
        }
    }
}
//1
//55
//66
//77
//5
//6
//7
//8
//9

4.2.2.从头拷贝指定长度的数组

方法如下:

数组拷贝:java.util.Arrays.copyOf(源数组名称,新数组长度)

示例代码如下:

import java.util.Arrays;

public class Test{
    public static void main(String[] args){
        int[] original = new int[]{1,3,5,7,9};
        int[] result = Arrays.copyOf(original,10);
        for (int temp : result) {
            System.out.println(temp);
        }
    }
}
//1
//3
//5
//7
//9
//0
//0
//0
//0
//0

5.数组案例

要求:给定一个数组,要求可以统计出该数组的最大值、最小值、平均值、总和

0

1

2

3

4

5

6

7

8

1

4

3

4

55

77

6

9

8

示例:简单实现如下

public class Test{
    public static void main(String[] args) {
        int[] data = new int[]{1,4,3,4,55,77,6,9,8};
        //假定第一个元素为最大值
        int max = data[0];
        //假定第一个元素为最小值
        int min = data[0];
        int sum = 0;
        double avg = 0d;
        for (int i = 0; i < data.length; i++) {
            sum += data[i];
            if(data[i] > max){
                max = data[i];
            }
            if(data[i] < min){
                min = data[i];
            }
        }
        avg = (double)sum / data.length;
        System.out.println("最大值为:" + max);
        System.out.println("最小值为:" + min);
        System.out.println("总和为:" + sum);
        System.out.println("平均值为:" + avg);
    }
}
//最大值为:77
//最小值为:1
//总和为:167
//平均值为:18.555555555555557

问题:主方法代码量太多。主方法相当于客户端,里面的代码越简单越好,所以进行如下改进,通过方法与数组互操作简化主方法代码,代码如下;

public class Test{
    public static void main(String[] args) {
        processData(new int[]{1,4,3,4,55,77,6,9,8});
    }
    public static void processData(int[] data){
        double[] result = new double[4];
        //最大值
        result[0] = data[0];
        //最小值
        result[1] = data[0];
        //总和
        result[2] = 0d;
        //平均值
        result[3] = data[0];
        for (int i = 0; i < data.length; i++) {
            result[2] += data[i];
            if(data[i] > result[0]){
                result[0] = data[i];
            }
            if(data[i] < result[1]){
                result[1] = data[i];
            }
        }
        result[3] = result[2]/data.length;
        System.out.println("最大值为:" + result[0]);
        System.out.println("最小值为:" + result[1]);
        System.out.println("总和为:" + result[2]);
        System.out.println("平均值为:" + result[3]);
    }
}
//最大值为:77.0
//最小值为:1.0
//总和为:167.0
//平均值为:18.555555555555557

6.数组对象

之前所有定义的数组都属于基本类型的数组,对象数组往往是以引用数据类型为主的定义,例如:类、接口。

6.1.对象数组的动态初始化

语法规则如下:

类名称[] 对象数组名称 = new 类名称[长度];

示例代码如下:

class Person{
    private String name;
    private int age;
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }
    public void getInfo(){
        System.out.println("姓名:" + name + "、年龄:" + age);
    }
}

public class Test{
    public static void main(String[] args) {
        //数组动态初始化,每个元素都是其对应数据类型的默认值
        Person[] per = new Person[3];
        per[0] = new Person("邹大宝",6);
        per[1] = new Person("邹二宝",4);
        per[2] = new Person("邹小宝",2);
        for(int i = 0; i < per.length; i ++){
            per[i].getInfo();
        }
    }
}
//姓名:邹大宝、年龄:6
//姓名:邹二宝、年龄:4
//姓名:邹小宝、年龄:2

6.2.对象数组静态初始化

示例代码如下:

class Person{
    private String name;
    private int age;
    public Person(String name,int age){
        this.name = name;
        this.age = age;
    }
    public void getInfo(){
        System.out.println("姓名:" + name + "、年龄:" + age);
    }
}

public class Test{
    public static void main(String[] args) {
        //数组动态初始化,每个元素都是其对应数据类型的默认值
        Person[] per = new Person[]{
            new Person("邹大宝",6),
            new Person("邹二宝",4),
            new Person("邹小宝",2)
        };
        for(int i = 0; i < per.length; i ++){
            per[i].getInfo();
        }
    }
}
//姓名:邹大宝、年龄:6
//姓名:邹二宝、年龄:4
//姓名:邹小宝、年龄:2

对象数组保存的内容要比普通数据类型要