4.Java基础知识:数组

1、数组

1.1 介绍

把具有相同类型的若干变量按有序的形式组织起来,这些按序排列的同类数据元素的集合称为数组。

1.2 格式一

元素类型[] 数组名 = new 元素类型[元素个数或数组长度];

示例 : int[] arr = new int[5];
  • 如何存储数据到数组之中

语法 :数组名[元素的下标] = 数据;

  • 如何去取存储在数组之中的数据

语法 : 数组名[元素的下标];

  • 如何遍历数组的元素:
public class Demo {
  public static void main(String[] args) {
  
    // 1. 元素类型[] 数组名 = new 元素类型[元素个数或数组长度];
    int[] arr = new int[5];
  
    //存数据
    arr[0] = 98;
    arr[1] = 88;
    arr[2] = 100;
    arr[3] = 80;
    arr[4] = 99;
  
    //取数据
    System.out.println("arr[0]=" + arr[0]);
    System.out.println("arr[1]=" + arr[1]);
    System.out.println("arr[2]=" + arr[2]);
    System.out.println("arr[3]=" + arr[3]);
    System.out.println("arr[4]=" + arr[4]);
  
    System.out.println("arr.length=" + arr.length);
    
    //遍历
    for (int i = 0; i < arr.length; i++) {
        System.out.println(arr[i]);
    }
  }
}

1.3 格式二

元素类型[] 数组名 = new 元素类型[] {元素, 元素, ......};

示例 :
int[] arr = new int[]{1, 3, 5, 7, 9};
int[] arr = {1, 3, 5, 7, 9};

1.4 总结

  • 数组是用来干嘛的?

数组是用来存储多个相同类型的数据。

  • 什么时候使用数组?

当有一组数据, 并且这组数据的意义是相同的, 意义相同,肯定类型就是一样的。

  • 如何创建数组?

两种创建数组的格式。

  • 几个术语

数组名, 数组元素, 数组下标, 数组长度。

  • 如何往数组中存储数据?

通过元素的下标进行数据的存储。

  • 如果取出数组中的数据?

通过元素的下标进行数据的获取。

  • 如果遍历数组中的数据?

通过 数组名.length 获取数组的长度,再使用for循环遍历即可。

  • 关于值传递与引用传递的区别

1.数值传递称为值传递,仅仅是将数值拷贝了一份,(副本) 在函数内部修改数值对源数据不会有任何影响.

2.引用传递,表示访问这个地址指向空间的值,直接对源数据进行操作.

2、查表法

数组空间中的值和数组的下标一一对应。因此我们可以将数组空间中值和下标的关系,当做一个表来看待,简称为查表法.

  • 打印星期 查表法
public class Demo {
    public static void main(String[] args) {
        String result = getWeek(6);
        System.out.println("result=" + result);
    }

    /*
    定义一个功能,根据给定的数据获取对应的星期.

    查表法 : 数据之间存在对应的关系. 通过关系中的一方来查询另一方.
    */
    public static String getWeek(int num) {
        // 0. 先判断, 用户传入的数据是否合法
        if (num > 7 || num < 1) {
            return num + "没有对应的星期";
        }
        // 1. 定义一个数组,存储固定的星期,这个称之为一个存储了对应关系的表
        String[] weeks = {"", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六", "星期日"};

        // 2. 根据用户存储的数值,作为索引,返回对应表中的数据即可.
        return weeks[num];
    }
}

3、选择排序

选择排序的基本思想是 :每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。

public class Demo {
    public static void main(String[] args) {
        int[] arr = {70, 80, 31, 37, 10, 1, 48, 60, 33, 80};
        selectionSort(arr);
    }

    // 功能: 将一组无序的数组进行有序的排列
    // 选择排序 (直接在内层循环中交换数值)
    public static void selectionSort(int[] array) {
        // 大圈套小圈
        // 外圈 i -> 行 循环了总共的 `轮数`
        // 内圈 j -> 列 拿到当前的 `轮数` 与之后的所有数进行比较
        for (int i = 0; i < array.length - 1; i++) {
            for (int j = i + 1; j < array.length; j++) {
                // 判断两个数值的大小,如果i下标的元素值比j下标的元素值大,需要交换对应下标的数值
                if (array[i] > array[j]) {
                    // 条件成立,交换数值
                    array[i] = array[i] ^ array[j];
                    array[j] = array[i] ^ array[j];
                    array[i] = array[i] ^ array[j];
                }
            }
        }
    }
}

4、冒泡排序

冒泡排序的基本思想是 : 每次比较两个相邻的元素,如果它们的顺序错误,就把它们交换过来。

public class Demo {
    public static void main(String[] args) {
        int[] arr = {12, 35, 99, 18, 76};
        bubbleSort(arr);
    }

    // 冒泡排序
    public static void bubbleSort(int[] array) {
        for (int i = 0; i < array.length - 1; i++) {
            for (int j = 0; j < array.length - 1 - i; j++) {
                // 判断
                if (array[j] > array[j + 1]) {
                    // 交互数值
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
        }
    }
}

5、查找元素

/*
无序 - 普通查找方式: 逐一遍历,进行元素的对比.
*/
public class Demo {
    public static void main(String[] args) {
        int[] arr = {11, 73, 54, 70, 18};
        int result = searchKey(arr, 18);
        System.out.println("result=" + result); // result=4
    }

    // 需求 : 查找一个元素在数组中的第一次出现的位置
    public static int searchKey(int[] array, int key) {
        for (int i = 0; i < array.length; i++) {
            if (array[i] == key) {
                return i;
            }
        }
        return -1; // -1 表示不存在该key. 没有找到.
    }

}

/*
折半查找 (有序数组)
*/
public class Demo {
    public static void main(String[] args) {
        int[] arr = {10, 20, 30, 40, 50, 60, 70, 80, 90};
        int result = binarySearch(arr, 50);
        System.out.println("result=" + result);
    }

    // 折半查找
    public static int binarySearch(int[] array, int key) {
        // 1. 定义两个变量,用来表示最小和最大查找下标
        int min = 0;
        int max = array.length - 1; // 下标最大数 = 数值长度 - 1;
        while (min <= max) {
            int mid = (min + max) / 2; // int mid = (min + max) >> 1;
            if (array[mid] > key) // 如果中间值大于key,就往左边找 (大了)
            {
                max = mid - 1;
            } else if (array[mid] < key) // 如果中间值小于key,就往右边找 (小了)
            {
                min = mid + 1;
            } else // 相等就是找到了,直接返回
            {
                return mid;
            }
        }
        return -1; // 循环条件结束,来到这里表示没有找到.
    }
}

6、获取插入点

寻找在有序数组中插入新元素下标的位置 (原理: 折半查找)

public class Demo {
    public static void main(String[] args) {
        // 1. 定义了一个整型数组
        int arr[] = {9, 12, 15, 24, 36, 41, 59, 68};  

        // 2. 寻找在有序数组中,插入新元素的下标位置
        int index = getIndexOfNewElement(arr, 41);

        // 3. 输出查看结果
        System.out.println("index=" + index);
    }

    // 功能 : 寻找在有序数组中,插入新元素的下标位置 (二分查找)
    public static int getIndexOfNewElement(int[] array, int key) {
        // 1. 定义两个变量,用于存储查找的最小下标和最大下标
        int min = 0;
        int max = array.length - 1;

        // 2. 循环查找和对比
        while (min <= max) {
            int mid = (min + max) >> 1;
            if (array[mid] < key) // 小了
            {
                min = mid + 1;
            } else if (array[mid] > key) // 大了
            {
                max = mid - 1;
            } else // 找到了
            {
                return mid;
            }
        }

        // 3. 循环结束后,都未返回,此时应该返回min表示的下标.
        return min;
    }
}

7、数组反转

public class Demo {
    public static void main(String[] args) {
        // 对一个给定的数组进行反转
        // 如 : {12, 23, 34, 45, 56} -> {56, 45, 34, 23, 12}

        // 1. 定义一个整型数组
        int[] arr = {12, 23, 34, 45, 56};

        // 2. 调用自定义函数实现数组的反转
        reverse(arr);

        // 3. 调用自定义函数将数组转成字符串
        String result = arrayToString(arr);

        // 4. 输出查看
        System.out.println(result);
    }

    // 功能: 将数组转成字符串
    public static String arrayToString(int[] array) {
        String temp = "[";
        for (int i = 0; i < array.length; i++) {
            if (i == array.length - 1) {
                temp = temp + array[i] + "]";
            } else {
                temp = temp + array[i] + ", ";
            }
        }
        return temp;
    }

    // 功能: 实现数组的反转
    public static void reverse(int[] array) {
        for (int start = 0, end = array.length - 1; start < end; start++, end--) {
            // 调用自定义函数实现两个整型数值的交换
            swap(array, start, end);
        }
    }

    // 功能: 实现两个整数数值的交换
    public static void swap(int[] array, int idx1, int idx2) {
        // 交换
        int temp = array[idx1];
        array[idx1] = array[idx2];
        array[idx2] = temp;
    }
}

8、二维数组

8.1 格式一

int[][] arr = new int[3][2];
  • 代码
public class Demo {
  public static void main(String[] args) {
  
    // 一维数组 : 相同类型数据的一个集合.数组名存储的是数组在堆区中的首地址.
    // 定义格式一:
    int[] array = new int[5];
    array[2] = 80;
  
    // 遍历一维数组
    for (int i = 0; i < array.length; i++) {
        System.out.println("array[" + i + "]=" + array[i]);
  
    }
    System.out.println("\n");
  
    // 二维数组 : 数组中的数组
    // 二维数组定义格式一 : 
    // 表示定义了一个长度为3的二维数组,二维数组中存储的都是一维数组.
    // 每一个一维数组的长度都是2.
    int[][] scores = new int[3][2]; // 指定了所有一维数组的长度
  
    // 需求: 给第二个二维数组下标为1的元素赋值 99
    scores[1][1] = 99;
  
    // 定义二维数组的时候,不指定一维数组的长度.
    int[][] arr = new int[3][];
  
    arr[0] = new int[3];
    arr[1] = new int[1];
    arr[2] = new int[2];
  
    // 要先验证一下二维数组和每一位一位数组的长度,观察是否和我们上面指定的是一致的.
    System.out.println("arr.length=" + arr.length); // 二维数组的长度
    System.out.println("arr[0].length=" + arr[0].length); // 二维数组中第0个一维数组的长度
    System.out.println("arr[1].length=" + arr[1].length); // 二维数组中第1个一维数组的长度
    System.out.println("arr[2].length=" + arr[2].length); // 二维数组中第2个一维数组的长度
  
    // 给二维数组中一维数组的元素进行赋值
    arr[0][1] = 88;
    arr[1][0] = 44;
    arr[2][1] = 99; // arr[2][2] = 99; 数组角标越界
  
    System.out.println("arr[0][0]=" + arr[0][0]);
    System.out.println("arr[0][1]=" + arr[0][1]);
    System.out.println("arr[0][2]=" + arr[0][2]);
    System.out.println("arr[1][0]=" + arr[1][0]);
    System.out.println("arr[2][0]=" + arr[2][0]);
    System.out.println("arr[2][1]=" + arr[2][1]);
  
    System.out.println("\n");
  
    // 观察发现,我们可以通过二维数组和一维数组的长度,最终来完成二维数组的遍历
    for (int i = 0; i < arr.length; i++) {
        for (int j = 0; j < arr[i].length; j++) {
            System.out.println("arr[" + i + "][" + j + "]=" + arr[i][j]);
        }
    }
  }
}

8.2 格式二

 int[][] arr = new int[3][];
  • 请将下列表格使用二维数组完成定义
组员1组员2组员3组员4
第一小组1112
第二小组212223
第三小组31323334
  • 代码
public class Demo {
    public static void main(String[] args) {
        // 定义一个长度为3的二维数组
        int[][] arr = new int[3][];
        // 为数组的元素赋值
        arr[0] = new int[]{11, 12};
        arr[1] = new int[]{21, 22, 23};
        arr[2] = new int[]{31, 32, 33, 34};
    }
}

8.3 格式三

int[][] arr = {{11, 12}, {21, 22, 23}, {31, 32, 33, 34}};
  • 例如要统计一个公司三个销售小组中每个小组的总销售额以及整个公司的销售额
组员1组员2组员3组员4
第一小组1112
第二小组212223
第三小组31323334
  • 代码
public class Demo {
    public static void main(String[] args) {
        
        // 1. 定义一个二维数组,并完成初始化
        int[][] arr = {{11, 12}, {21, 22, 23}, {31, 32, 33, 34}};

        // 2. 需要两个变量,一个用于统计每个小组的总销售额,另外一个用于统计整个公司的总销售额.
        int sum = 0;
        int groupSum = 0;

        // 3. 遍历二维数组
        for (int i = 0; i < arr.length; i++) {
            // 每组的总销售额需要在外层循环中进行清空
            groupSum = 0;

            for (int j = 0; j < arr[i].length; j++) {
                // 在内层循环中累加该小组每位成员的个人销售额
                groupSum += arr[i][j];
            }
            // 在外层循环中累加小组的总销售额
            sum += groupSum;
            // 打印输出查看每个小组的总销售额
            System.out.println("第" + (i + 1) + "个小组的总销售额为:" + groupSum);
        }

        // 4. 循环结束之后,sum存储的就是公司总销售额
        System.out.println("公司总销售额为:" + sum);
    }
}