007 数组

本贴最后更新于 2054 天前,其中的信息可能已经时移世易

本文为《Java 语言程序设计》第十版 章节笔记

007 一维数组

Java 和许多高级语言都提供了一种称作 数组(array) 的数据结构,可以用它来存储一个元素个数固定且元素类型相同的有序集。

7.1 数组的基础知识

一旦数组被创建,它的大小是固定的。使用一个数组引用变量,通过下标来访问数组中的元素。

声明数组变量的语法:

elementType[] arrayRefVar;//(元素类型[] 数组引用变量)

elementType 可以是任意数据类型,但是数组中所有的元素都必须具有相同的数据类型。

不同于基本数据类型变量的声明,声明一个数组变量时并不在内存中给数组分配 任何空间。它只是创建一个对数组的引用的存储位置。如果变量不包含对数组的引用,那么这个变量的值为 null。除非数组已经被创建,否则不能给它分配任何元素。

声明一个数组变量、创建数组、然后将数组引用赋值给变量这三个步骤可以合并在一条语句里,如下所示:
elementType[] arrayReVar = new elementType[arraySize];
(元素类型[] 数组引用变量 = new 元素类型[数组大小]; )

当创建数组后,它的元素被赋予默认值,数值型基本类型的默认值为 0,char 型的默认值为'\u0000',boolean 型的默认值为 false。

数组的下标是基于 0 的,也就是说,其范围从 0 开始到 arrayReVar.length-1 结束。

使用数组初始化语法时,必须将声明、创建和初始化数组都放在一条语句中。

处理数组:

  1. 使用输入值初始化数组
    java.tuil.Scanner input = new java.util.Scanner(System.in);
    System.out.print("Enter" + myList.length + " values: ");
    for (int i = 0; i < myList.length; i++){
        myList[i] = input.nextDouble();
    }
    
  2. 使用随机数初始化数组
    for (int i = 0; i < myList.length; i++){
        myList[i] = Math.random() * 100;
    }
    
  3. 显示数组
    for (int i = 0; i < myList.length; i++){
        System.out.print(myList[i] + " ");
    }
    
    对于 char[]类型的数组,可以使用一条打印语句显示数组,例如:
    char[] city = {'D', 'a', 'l', 'l', 'a', 's'};
    System.out.print(city);
    ````
    
  4. 对所有元素求和
    double total = 0;
    for (int i = 0; i < myList.length; i++){
        total += myList[i];
    }
    
  5. 找出最大元素
    double max = myList[0];
    for (int i = 0; i < myList.length; i++){
        if (myList[0] > max){
            max = myList[i];
        }
    }
    
  6. 找出最大元素的最小下标
    double max = myList[0];
    int indexOfMax = 0;
    for (int i = 1; i < myList.length; i++){
        if (myList[i] > max) {
            max = myList[i];
            indexOfMax = i;
        }
    }
    
  7. 随机打乱(shuffling)
    for (int i = myList.length - 1; i > 0; i--){
        // Generate an index j randomly with 0 <= j <= i
        int j = (int)(Math.random() * (i + 1));
    
        // Swap myList[i] with myList[j]
        double temp = myList[i];
        myList[i] = myList[j];
        myList[j] = temp;
    }
    
  8. 移动元素(左移或右移)
    double temp = myList[0]; // Retain the first element
    
    // Shift element left
    for (int i = 1; i < myList.length; i++){
        myList[i - 1] = myList[i];
    }
    
    // Move the first element to fill the last position
    myList[myList.length - 1] = temp;
    
  9. 简化编码
    例如,输入月份数字,获得月份名称:
    String[] months = {"January", "February",..., "December"};
    System.out.print("Enter a month number (1 to 12): ");
    int minthNumber = input.nextInt();
    System.out.print("The month is " + months[monthNumber - 1]);
    

foreach 循环
Java 支持一个简便的 for 循环,称为 foreach 循环,即不使用下标变量就可以顺序地遍历整个数组。例如:

for (double e: myList) {
    System.out.println(e);
}
// "对myList中每个元素e 进行一下操作"。注意,变量 e 必须声明为与myList中元素相同的数据类型。

语法:

for (elementType element: arrayReVar) {
    // Process the element
}

7.2 数组的复制

要将一个数组中的内容复制到另一个中,需要将数组的每个元素复制到另一个数组中。

在 Java 中,可以使用赋值语句复制基本数据类型的变量,但不能复制数组。

复制数组有三种方法:

  1. 使用循环语句逐个地复制数组的元素。

    int[] sourceArray = {2, 3, 1, 5, 10};
    int[] targetArray = new int[soutceArray.length];
    for (int i = 0; i < soutceArray.length; i++) {
        targetArray[i] = sourceArray[i];
    }
    
  2. 使用 System 类中的静态方法 arraycopy。

    arraycopy(sourceArray, srcPos, targetArray, tarPos, length);
    // 参数srcPos 和 tarPos 分别为原数组 sourceArray 和  
    // 目标数组targetArray 中的起始位置,length为复制元素的个数
    

    完整复制为:

    System.arraycopy(sourceArray, 0, targetArray, 0, sourceArray.length);
    

    arraycopy 方法没有给目标数组分配内存空间,复制前必须创建目标数组以及分配给它内存空间。复制完成后,sourceArray 和 targetArray 具有相同的内容,但占有独立的内存空间。

  3. 使用 clone 方法复制数组。
    13 章介绍

7.3 将数组传递给方法

  • 对于基本数据类型参数,传递的是实参的值。
  • 对于数组类型参数,参数值是数组的引用,给方法传递的是这个引用。从语义上来讲,最好的描述就是参数传递的是共享信息(pass-by-sharing),即方法中的数组和传递的数组是一样的。所以,如果改变方法中的数组,将会看到方法外的数组也改变了。

数组在 Java 中是对象,JVM 将对象存储在一个称为堆(heap)的内存区域中,堆用于动态内存分配。(方法在栈中)

7.4 可变长参数列表

具有同类型的可变长度的参数可以传递给方法,并将作为数组对待。

方法声明如下:

typeName...parameterName // (类型名...参数名)

e.g:

public class VarArgsDemo{
    public static void main(String[] args) {
        printMax(34, 3, 3, 2, 56.5);
        printMax(new double[]{1, 2, 3});
    }

    public static void printMax(double... number) {
        if (number.length == 0) {
            System.out.println("No argument passed");
            return;
        }

        double result = numbers[0];

        for (int i = 1; i < numbers.length; i++){
            result = numbers[i];
        }

        System.out.println("The max value is " + result);
    }
}

7.5 数组的查找

如果一个数组排好序了,对于寻找数组中的一个元素,二分查找比线性查找更加高效。

两种常用的方法:

  • 线性查找(linear searching)

    public class LinearSearch {
        /** The method for finding a key in the list */
        public static int linearSearch(int[[] list, int key) {
            for (int i = 0; i < list.length; i++) {
                if (key == list[i]) {
                return i;
            }
            return -1;
        }
    }
    

    如果匹配成功,返回与关键字匹配的元素在数组中的下标。如果没有匹配成功,则返回-1。
    数组中的元素可以按任意顺序排列。

  • 二分查找(binary searching)(使用二分查找法的前提条件是数组中的元素只需已经排好序。)

    public class BinarySearch {
        /** Use binary search to find the key in the list */
        public static int binarySearch(int[] list, int key) {
            int low = 0;
            int high = list.length - 1;
    
            while (hgih >= low) {
                int mid = (low + high) / 2;
    
                if (key < list[mid]) {
                    high = mid - 1;
                } else if (key == list[mid]) {
                    return mid;
                } else {
                    low = mid + 1;
                }
            }
    
            return -low - 1; // Now hig < low, key not found
        }
    }
    

    此方法数组按升序排好。匹配成功,返回下标。如果关键字不在该序列中,方法返回-low-1,不仅表明关键字不在序列中,而且还给了关键字应该插入的位置(index = low)。

7.6 数组的排序

选择排序:假设要按升序排列一个数列。先找到数列中最小的数,然后将它第一个元素交换。接下来,在剩下的数中找到最小数,将它和第二个元素交换,以此类推,直到数列中仅剩一个数为止。

public class SelectionSort {
    /** The method for sorting the numbers */
    public static void selectionSort(double[] list) {
        for (int i = 0; i < list.length - 1; i++) {
            // Find the minimum in the list[i...list.length-1]
            double currentMin = list[i];
            int currentMinIndex = i;

            for (int j = i + 1; j < list.length; j++) {
                if (currentMin > list[j]) {
                    currentMin = list[j];
                    currentMinIndex = j;
                }
            }

            // Swap list[i] with list[currentMinIndex] if necessary
            if (currentMinIndex != i) {
                list[currentMinIndex] = lsit[i];
                lsit[i] = current;
            }
        }
    }
}

7.6 Arrays 类

java.tuil.Arrays 类包含一些实用的方法用于常见的数组操作,比如排序和查找。

  1. 使用 sort 或者 parallelSort 方法对整个数组或部分数组进行排序。

    double[] numbers = {6.0, 4.4, 1.9, 3.4, 3.5};
    java.util.Arrays.sort(numbers); // Sort the whole array
    java.uril.Arrays.parallelSort(numbers); // Sort the whole array
    
    char[] chars = {'a', 'A', '4', 'F', 'D', 'P'};
    java.util.Arrays.sort(chars, 1, 3); // Sort part of the array
    java.tuil.Arrays.parallelSort(chars, 1, 3); // Sort part of the array
    

    可以调用 sort(chars, 1, 3) 对从 chars[1]chars[3-1] 的部分数组排序。

  2. 采用二分查找法在数组中查找关键字。

    int[] lsit = {2, 4, 7, 10, 11, 45, 50, 59, 60, 66, 69, 70, 79};
    System.out.println("1. Index is " + java.tuil.Arrays.binarySearch(list, 11));
    System.out.println("2. Index is " + java.util.Arrays.binarySearch(lsit, 12));
    
    char[] chars = {'a', 'c', 'g', 'x', 'y', 'z'};
    System.out.println("3. Index is " + java.util.Arrays.binarySearch(chars, 'a'));
    System.out.println("4. Index is " + java.util.Arrays.binarySearch(chars, 't'));
    /** Output:
    *1. Index is 4
    *2. Index is -6
    *3. Index is 0
    *4. Index is -4
    */
    
  3. 可以采用 equals 方法检测两个数组是否相等

    int[] list1 = {2, 4, 7, 10};
    int[] list2 = {2, 4, 7, 10};
    int[] list3 = {4, 2, 7, 10};
    System.out.println(java.util.Arrays.equals(list1, list2));
    System.out.println(java.util.Arrays.equals(list1, list3));
    
  4. 可以使用 fill 方法填充整个数组或部分数组

  5. Arrays.toString()

008 多维数组

二维数组的基础知识

语法

数据类型 [][] 数组名;

二维数组装的两个下标,一个表示行,另一个表示列。

Java 中每个下标必须放在一对方括号中。

获取二维数组的长度

分别获取每行的一维数组的长度

x[0].length、x[1].length...

锯齿数组

二维数组的每行的长度不一样。

处理二维数组

嵌套的 for 循环 常用来处理二维数组

将二维数组传递给方法

将一个二维数组传递给方法的时候,数组的引用传递给了方法。

多维数组

二维数组由一个一维数组的数组组成,三维数组则可以认为是由一个二维数组的数组组成。

  • Java

    Java 是一种可以撰写跨平台应用软件的面向对象的程序设计语言,是由 Sun Microsystems 公司于 1995 年 5 月推出的。Java 技术具有卓越的通用性、高效性、平台移植性和安全性。

    3169 引用 • 8207 回帖 • 1 关注

相关帖子

回帖

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...