Java中的数组(详细案例)

目录

数组

一、概念

二、数组的创建和组成

2.1 数组的创建

2.2 数组的组成

三、数组的访问

3.1 直接访问

3.2 下标越界问题

3.3 数组的遍历

3.4 数组的默认值

3.5 数组的常见创建方式

四、数组的扩容

4.1 扩容的步骤

4.2 System.arrayCopy复制数组

4.3 使用Arrays.copyOf复制数组

五、引用传递和值传递

六、可变长参数

七、数组的排序

7.1 冒泡排序

7.2 选择排序

7.3 插入排序

7.4 JDK排序

八、二维数组


数组

一、概念

当需要存储多个相同类型的变量时,如果定义多个变量,比较麻烦,而且不方便统一操作。

此时应该使用数组。

数组是在内存中定义一块连续的空间,存储相同类型的数据。

  • 连续空间

  • 长度在创建时就固定

  • 存储相同类型数据

注意:数组是引用数据类型。

二、数组的创建和组成

2.1 数组的创建

创建数组时,指定类型和长度。

public class Test1 {
    public static void main(String[] args) {
        // 类型是int数组,表示在该数组存储的数据是int类型
        // 5表示数组的长度,意味着能存储5个int类型的数据
        int [] arr1 = new int[5];
        
        // 存储7个double类型的数据的一块连续空间
        double [] arr2 = new double[7];
        
        // 存储8个String类型的数据的一块连续空间
        String [] arr3 = new String[8];
    }
}

2.2 数组的组成

数组是一块连续的空间,数组名相当于数组的首地址,当访问数据元素时,通过数组名+下标的形式访问。例如:arr[0]表示数组名为arr,0表示下标,代表第一个元素。

如果数组有5个元素,下标为0~4,

三、数组的访问

3.1 直接访问

public class Test2 {
    // 赋值和取值
    public static void main(String[] args) {
        // 类型是int数组,表示在该数组存储的数据是int类型
        // 5表示数组的长度,意味着能存储5个int类型的数据
        int [] arr1 = new int[5];
        
        // 赋值
        arr1[0] = 20;
        arr1[1] = 30;
        arr1[2] = 40;
        arr1[3] = 50;
        arr1[4] = 60;
        
        // 取值
        System.out.println(arr1[0]);
        System.out.println(arr1[1]);
        System.out.println(arr1[2]);
        System.out.println(arr1[3]);
        System.out.println(arr1[4]);
//      System.out.println(arr1[5]); // 下标越界
    }
}

3.2 下标越界问题

当访问的下标超出范围,如上面的代码,如果使用了arr1[5],就会出现异常,该异常为:

java.lang.ArrayIndexOutOfBoundsException

3.3 数组的遍历

使用循环来对数组所有的元素进行访问。

注意:数组使用length来表示长度。

public class Test2 {
    // 赋值和取值
    public static void main(String[] args) {
        // 类型是int数组,表示在该数组存储的数据是int类型
        // 5表示数组的长度,意味着能存储5个int类型的数据
        int [] arr1 = new int[5];
        
        // 赋值
        arr1[0] = 20;
        arr1[1] = 30;
        arr1[2] = 40;
        arr1[3] = 50;
        arr1[4] = 60;
        
        // 循环遍历
        for (int i = 0; i < arr1.length; i++) {
            System.out.println(arr1[i]);
        }
    }
}

3.4 数组的默认值

当数组创建后,如果没有给元素赋值,会使用默认值,不同类型的数组默认值不一样。

整数类型,默认值都是0

小数类型,默认值是0.0

布尔类型,默认值为false

字符类型,默认值为0

其他类型,默认值为null

null是Java中的关键字,表示没有分配空间,空值。

public class Test3 {
    // 数组的默认值
    public static void main(String[] args) {
        // 局部变量需要先赋值才能取值
//      int n;
//      System.out.println(n); // 报错
        
        int [] arr = new int[5];
        
        // 数组元素没有赋值时,是使用的默认值
        // 
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        } 
    }
}

3.5 数组的常见创建方式

public class Test4 {
    // 数组的创建方式
    public static void main(String[] args) {
        // 1、先声明,后分配空间
        int arr1 []; // int [] arr2;
        arr1 = new int[3];
        
        // 2、声明同时分配空间
        int [] arr2 = new int[3];
        
        // 3、声明并赋值,注意:会自动推断数组的长度,不允许写入长度
        int [] arr3 = new int[] {20, 30, 40};
        
        // 4、声明并赋值,简化版
        int [] arr4 = {20, 30, 40};
        
        // 如果要使用先声明,后分配空间的同时赋值
        int [] arr5;
        arr5 = new int[] {20, 30, 40, 50};
        
        // 不能简写
        int [] arr6;
//      arr6 = {20, 30, 40, 50}; // 报错
    }
}

案例1:

public class Test5 {
    // 给定一个数组长度为10,赋值100以内随机数,打印所有的数字以及其平均数
    public static void main(String[] args) {
        // 定义数组,长度为10
        int [] arr = new int[10];
        
        // 定义和值
        int sum = 0;
        // 赋值并求和
        Random random = new Random();
        for (int i = 0; i < arr.length; i++) {
            arr[i] = random.nextInt(100);
            sum += arr[i]; // 求和
        }
        
        // 打印输出
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
        // 打印平均数
        double avg = (double)sum / arr.length;
        System.out.println("平均数为:" + avg);
    }
}

案例2:

public class Test6 {
    // 输入一个数字,判断数组中是否包含该数字,如果包含,输出下标,不包含则输出-1
    public static void main(String[] args) {
        Scanner input = new Scanner(System.in);
        
        // 给定一个数组
        int [] arr = {12, 34, 745, 88, 98};
        
        // 接收一个数字
        System.out.println("请输入一个数字:");
        int num = input.nextInt();
        
        int index = -1; // 定义下标
        for (int i = 0; i < arr.length; i++) {
            if(num == arr[i]) {
                index = i; // 将下标记住
                break;
            }
        }
        
        System.out.println("下标为:" + index);
    }
}

案例3:将数组元素反序。

四、数组的扩容

4.1 扩容的步骤

数组长度是固定的,所以如果数组中的元素满了,需要再向数组中添加元素,需要扩容。

扩容的步骤是:

  • 1、创建一个新的数组,长度需要足够

  • 2、将原数组中的元素放入到新数组中,并将新添加的元素顺序放入到新数组中

public class Test9 {
    // 数组扩容
    public static void main(String[] args) {
        int [] arr = {12, 34, 745, 88, 98};
​
        // 创建一个新的数组
        int [] arr1 = new int[arr.length + 1];
        
        // 将原数组中的元素放入到新数组中
        for (int i = 0; i < arr.length; i++) {
            arr1[i] = arr[i];
        }
        
        // 添加新元素
        arr1[arr.length] = 50;
        
        // 输出新数组
        System.out.println(Arrays.toString(arr1));
    }
}
public class Test10 {
    // 向数组中添加元素
    public static void main(String[] args) {
        int [] arr = {12, 34, 745, 88, 98};
​
        arr = add(arr, 35);
        
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
​
    public static int[] add(int[] arr, int num) {
        // 创建一个新数组
        int [] newArray = new int[arr.length + 1];
        // 将原数组中的内容复制到新数组中
        for (int i = 0; i < arr.length; i++) {
            newArray[i] = arr[i];
        }
        // 将要添加的元素添加到新数组的最后
        newArray[arr.length] = num;
        return newArray;
    }
}

4.2 System.arrayCopy复制数组

可以使用系统自带方法来复制数组中的内容。

案例:数组的合并

public class Test12 {
    // 数组合并
    public static void main(String[] args) {
        int [] arr1 = {1, 2, 3, 4, 5}; // 数组1
        int [] arr2 = {6, 7, 8, 9}; // 数组2
​
        // 创建新数组长度为数组1和数组2长度之和
        int [] newArray = new int[arr1.length + arr2.length];
        
//      // 将数组1的元素复制到新数组中
//      for (int i = 0; i < arr1.length; i++) {
//          newArray[i] = arr1[i];
//      }
//      
//      // 将数组2的元素复制到新数组中
//      for (int i = 0; i < arr2.length; i++) {
//          newArray[arr1.length + i] = arr2[i];
//      }
        
        System.arraycopy(arr1, 0, newArray, 0, arr1.length);
        System.arraycopy(arr2, 0, newArray, arr1.length, arr2.length);
        
        System.out.println(Arrays.toString(newArray));
    }
}

4.3 使用Arrays.copyOf复制数组

copyOf方法是在复制原数组的基础上创建一个新数组,并返回。

public class Test13 {
    // 使用copyOf数组合并
    public static void main(String[] args) {
        int [] arr1 = {1, 2, 3, 4, 5}; // 数组1
        int [] arr2 = {6, 7, 8, 9}; // 数组2
​
        int [] newArray = join(arr1, arr2);
        
        System.out.println(Arrays.toString(newArray));
    }
​
    public static int[] join(int [] arr1, int [] arr2) {
        // 完全复制arr1并创建一个指定长度的新数组
        int [] newArray = Arrays.copyOf(arr1, arr1.length + arr2.length);
        System.arraycopy(arr2, 0, newArray, arr1.length, arr2.length);
        return newArray;
    }
}

Arrays类是系统提供的多个操作数组的方法的封装。

五、引用传递和值传递

基本数据类型在传递时是值传递。

引用数据类型在传递是引用传递。

public class Test14 {
    // 引用传递
    public static void main(String[] args) {
        // 基本数据类型值传递
        int n = 5;
        int m = n;
        m = 8;
        System.out.println(n);
        
        // 引用数据类型引用(地址)传递
        int [] arr1 = {1, 2, 3, 4, 5};
        int [] arr2 = arr1;
        arr1[2] = 10;
        System.out.println(arr2[2]);
        
        // 在方法参数时也是值传递
        int i = 3;
        m1(i);
        System.out.println(i);
        
        // 方法参数传递时,如果是数组,是引用传递
        int [] arr3 = {1, 2, 3, 4, 5};
        m2(arr3);
        System.out.println(arr3[1]);
    }
​
    public static void m2(int [] arr) {
        arr[1] = 10;
    }
    
    public static void m1(int m) {
        m = 8;
    }
}

将数组作为参数传入到方法中,如果方法中只对数组元素进行操作,那么外部的数组也会发生变化,因为是同一个地址,但是如果在方法中创建了新的数组,外部想访问新的数组,应该将该数组作为返回值返回。

public class Test15 {
    // 演示方法中创建数组
    public static void main(String[] args) {
        int [] arr = {1, 2, 3, 4, 5};
        arr = m1(arr);
        System.out.println(Arrays.toString(arr));
    }
​
    public static int[] m1(int [] arr1) {
        arr1 = new int[6];
        for (int i = 0; i < arr1.length; i++) {
            arr1[i] = i + 1;
        }
        return arr1;
    }
}

六、可变长参数

简化数组作为方法参数时的调用过程,与数组使用类似。

语法:在方法的参数中使用类型... 来表示数组。

例如:

public class Test1 {
    public static void main(String[] args) {
        printArr();
        printArr(1);
        printArr(1, 3, 5);
    }
    
​
    public static void printArr(int... arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.println(arr[i]);
        }
    }
}

注意:

  • 只能作用在方法的参数,不能用来定义变量。

  • 只能写在方法参数列表中的最后一个参数。

  • 参数列表中只能有一个可变参数。

七、数组的排序

排序是指将数组中的元素按照指定的顺序进行排列,让数组中的元素变成有序的序列。

很多查找算法需要在有序序列中进行,所以排序是有必要的,而且排序本身就是一种算法。

1、冒泡排序

2、选择排序

3、插入排序

7.1 冒泡排序

public class Test2 {
    // 冒泡排序
    public static void main(String[] args) {
        int [] arr = {90, 12, 35, 80, 54, 7, 4, 15};
        // 需要的轮次,arr.length - 1
        // 比较时使用的下标:i,i + 1
        // 比较的次数,第0轮arr.length - 1次,
        //      第1轮 arr.length - 2,第2轮 arr.length - 3,第n轮arr.length - n - 1
        // 比较过程中,如果需要由小到大排序,那么下标i比i+1的数字要大,则进行交换
        // 12, 35, 80, 54, 7, 4, 15,            90
        // 12, 35, 54, 7, 4, 15,            80  90
        // 12, 35, 7, 4, 15,            54  80  90
    
        
        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = 0; j < arr.length - i - 1; j++) {
                if(arr[j] > arr[j + 1]) {
                    arr[j] = arr[j] ^ arr[j + 1];
                    arr[j + 1] = arr[j] ^ arr[j + 1];
                    arr[j] = arr[j] ^ arr[j + 1];
                }
            }
        }
        
        System.out.println(Arrays.toString(arr));
    }
}

7.2 选择排序

public class Test3 {
    // 选择排序
    public static void main(String[] args) {
        int [] arr = {90, 12, 35, 80, 54, 7, 4, 15};
        // 需要的轮次,arr.length - 1
        // 比较时使用的下标:i,j, min
        // 交换是交换的i和min
        // 比较的次数j
        // j的值从1开始,每轮都加1,j的值应该等于i+1
        // 4, 12, 35, 80, 54, 7, 90, 15
        // 4, 7, 35, 80, 54, 12, 90, 15
        // 4, 7, 12, 80, 54, 35, 90, 15
        // 4, 7, 12, 15, 54, 35, 90, 80
        
        for (int i = 0; i < arr.length - 1; i++) {
            int min = i; // 记住当前位置
            // 循环后面的元素,用比较的方式寻找最小元素的下标
            for (int j = i + 1; j < arr.length; j++) {
                if(arr[j] < arr[min]) {
                    min = j;
                }
            }
            
            // 如果最小元素下标不是当前轮次对应下标的元素,则进行交换
            if(min != i) {
                int temp = arr[min];
                arr[min] = arr[i];
                arr[i] = temp;
            }
        }
        
        System.out.println(Arrays.toString(arr));
    }
}

7.3 插入排序

public class Test4 {
    // 插入排序
    public static void main(String[] args) {
        int [] arr = {90, 12, 35, 80, 54, 7, 4, 15};
        // 需要的轮次,arr.length - 1
        // 比较时使用的下标:i,j, min
        // 12, 90, 35, 80, 54, 7, 4, 15
        // 12, 35, 90, 80, 54, 7, 4, 15
        // 12, 35, 80, 90, 54, 7, 4, 15
        // 12, 35, 54, 80, 90, 7, 4, 15
        //                  i  j
        
        for (int i = 0; i < arr.length - 1; i++) {
            int j = i + 1; // 需要比较的下标
            int num = arr[j]; // 记住当前元素
            for (; j > 0; j--) { // 向前循环比较
                if(num < arr[j-1]) { // 当前元素如果比前面的元素小,前面的元素需要向后移动
                    arr[j] = arr[j-1]; // 向后移动
                }else { // 当不需要移动时,当前位置即是需要比较的元素所占据的位置,停止循环,记住位置
                    break;
                }
            }
            arr[j] = num; // 将该位置插入当前比较的元素,如果循环完毕,说明该元素应该放到最前面
        }
        
        System.out.println(Arrays.toString(arr));
    }
}

7.4 JDK排序

public class Test5 {
    // JDK排序
    public static void main(String[] args) {
        int [] arr = {90, 12, 35, 80, 54, 7, 4, 15};
        
        // 排序
        Arrays.sort(arr);
        
        System.out.println(Arrays.toString(arr));
    }
}

八、二维数组

public class Test6 {
    // 多维数组
    public static void main(String[] args) {
        // 直接定义并赋值
        int [][] arr = {
                {1, 2},
                {3, 4, 5, 6},
                {7, 8, 9}
        };
        
        System.out.println(arr[0][1]);
        
        // 先分配行空间
        int [][] arr1 = new int[5][];
        // 循环行
        for (int i = 0; i < arr1.length; i++) {
            arr1[i] = new int[5]; // 分配列空间
            for (int j = 0; j < arr1[i].length; j++) {
                arr1[i][j] = (i) * 5 + (j+1); 
            }
        }
        
//      for (int i = 0; i < arr1.length; i++) { // 行
//          for (int j = 0; j < arr1[i].length; j++) { // 列
//              System.out.println(arr1[i][j]);
//          }
//      }
        
        System.out.println(Arrays.deepToString(arr1));
        
        int [][] arr2 = new int[5][5];
        
        int [] arr3 [];
    }
}

案例:杨辉三角

1

1 1

1 2 1

1 3 3 1

1 4 6 4 1

1 5 10 10 5 1

public class Test7 {
    // 杨辉三角
    public static void main(String[] args) {
        int row = 10;
        int [][] arr = new int[row][];
        
        // 赋值
        for (int i = 0; i < arr.length; i++) {
            arr[i] = new int[i+1];
            for (int j = 0; j < arr[i].length; j++) {
                if(j == 0 || j == arr[i].length - 1) {
                    arr[i][j] = 1;
                }else {
                    arr[i][j] = arr[i-1][j] + arr[i-1][j-1];
                }
            }
        }
        
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                System.out.print(arr[i][j] + "\t");
            }
            System.out.println();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/asdf12388999/article/details/127117117