Java入门(四)之 数组的定义与使用

数组基本用法

什么是数组

数组:一块连续的内存,且存储的是相同数据类型的集合。
数组本质上就是让我们能 “批量” 创建相同类型的变量。
例如:

  1. 如果需要表示两个数据, 那么直接创建两个变量即可 int a;int b。
  2. 如果需要表示五个数据, 那么可以创建五个变量 int a1; int a2; int a3; int a4; int a5;。
  3. 但是如果需要表示未知个数据,那么就不能创建未知个变量了。这时候就需要使用数组,帮我们批量创建。

注意事项:在 Java 中,数组中包含的变量必须是相同类型的。

创建数组

基本语法

// 动态初始化
数据类型[] 数组名称 = new 数据类型 [] {
    
     初始化数据 };
// 静态初始化
数据类型[] 数组名称 = {
    
     初始化数据 };

代码示例如下

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] array1 = {
    
    1,2,3,4,5,6};//1.定义且初始化一个数组(静态初始化)。
        int[] array2 = new int[10];//2.定义了一个数组,但是没有初始化。new 关键字不可缺。
        int[] array3 = new int[]{
    
    1,2,3,4,5,6,7,8,9};//3.动态初始化数组。
    }
}

这个代码中,array1,array2,array3 都是局部变量;而{1,2,3,4,5,6},new int[10],{1,2,3,4,5,6,7,8,9}都是存放在堆区的。
在这里插入图片描述

注意: 数组,实际上是数组对象
在这里插入图片描述
引用不一定在栈上,取决于变量的位置。当变量做局部变量时,引用才在栈上。
在这里插入图片描述

所谓的 “引用” 本质上只是存了一个地址,Java 将数组设定成引用类型,这样的话后续进行数组参数传参,其实只是将数组的地址传入到函数形参中,这样可以避免对整个数组的拷贝(当数组可能比较长时, 拷贝开销就会很大)。

数组的使用

使用数组做局部变量时,必须对其初始化;若不知道引用对象,应使用引用对应的零值(null)。
我们来打印数组作为示例

import java.util.*;

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] array = {
    
    1,2,3,4,5,6};
        int[] array2 = null;//array2 这个引用,不指向任何对象。
        //此时,我们来打印创建好的数组array。
        //3种方法
        //1.for 循环     length:数组的属性
        for (int i = 0; i < array.length;i++){
    
    
            System.out.print(array[i]+ " ");
        }
        System.out.println();
        //2.增强型for each循环
        for (int x :array) {
    
    
            System.out.print(x+ " ");
        }
        System.out.println();
        //3.使用操作数组工具类。
        //Arrays.toString 将数组以字符串的形式进行输出。
        /*String ret = Arrays.toString(array);
        System.out.println(ret);*/
        System.out.println(Arrays.toString(array));
    }
}

运行结果如下
在这里插入图片描述
这是三种打印数组的方式。
其中for()循环与for each () 循环的区别,for 循环通过下标 [ i ] 进行遍历整个数组;而for each () 循环遍历数组是不需要通过下标的。

注意事项

  1. 使用 array.length 能够获取到数组的长度。这个操作为成员访问操作符,在后期在面向对象中会经常用到。
  2. 使用 [ ] 按下标取数组元素。需要注意,下标从 0 开始计数。
  3. 使用 [ ] 操作既能读取数据,也能修改数据。
  4. 下标访问操作不能超出有效范围 [0, length - 1], 如果超出有效范围, 会出现下标越界异常。
import java.util.*;

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] array = {
    
    1,2,3,4,5,6};
        System.out.println(array[100]);
    }

运行结果如下
数组下标超出范围
这个异常的原因是数组下标超出范围(数组越界访问了)。

数组作为方法的参数

基本用法

我们还是用打印数组内容作为示例

public class TextDemo {
    
    
	public static void main(String[] args) {
    
    
		int[] arr = {
    
    1, 2, 3};
		printArray(arr);
		}
	public static void printArray(int[] a) {
    
    
		for (int x : a) {
    
    
			System.out.println(x);
			}
		}
}

运行结果如下
在这里插入图片描述
在这个代码中:

  1. int[] a 是函数的形参, int[] arr 是函数实参。
  2. 如果需要获取到数组长度, 同样可以使用 a.length

理解引用类型

一.参数传内置类型,代码如下:

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int num = 0;
        func(num);
        System.out.println("num = " + num);
    }
    public static void func(int x) {
    
    
        x = 10;
        System.out.println("x = " + x);
    }
}

执行结果
在这里插入图片描述
可以看出,修改形参 x 的值,不影响实参的 num 值。
在这里插入图片描述
二.参数传数组类型,代码如下:

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    1, 2, 3};
        func(arr);
        System.out.println("arr[0] = " + arr[0]);
    }
    public static void func(int[] a) {
    
    
        a[0] = 10;
        System.out.println("a[0] = " + a[0]);
    }
}

执行结果
在这里插入图片描述
可以看出,在函数内部修改数组内容,函数外部也发生改变。
此时数组名 arr 是一个 “引用” 。当传参的时候,是按照引用传参的。

认识 null

null 在 Java 中表示 “空引用” ,也就是一个无效的引用。

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = null;
        System.out.println(arr[0]);
    }
}

执行结果如下
在这里插入图片描述
这是因为,null 的作用类似于 C 语言中的 NULL (空指针),都是表示一个无效的内存位置。因此不能对这个内存进行任何读写操作。一旦尝试读写,就会抛出 NullPointerException异常。

初识 JVM 内存区域划分

在这里插入图片描述

JVM Stack 虚拟机栈 :就是我们平时所说的栈,用来存储局部变量。
Native Method Stack 本地方法栈:C/C++代码。
Heap 堆:new 创建的对象都是在堆上保存,用来存放对象。
PC Register 程序计数器:只是一个很小的空间,用来保存下一条执行的指令的地址。
Method Area 方法区:用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。方法编译出的的字节码就是保存在这个区域。
Runtime Constant Pool 方法运行池:存放字面量(字符串常量)与符号引用。(从 JDK1.7 开始, 运行时常量池在堆上)

数组作为方法的返回值

将原来数组的值,扩大二倍。改变原数组。

import java.util.*;

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] array = {
    
    1,2,3,4,5};
        System.out.println("数组扩大二倍前打印");
        System.out.println(Arrays.toString(array));
        int[] ret = fun(array);
        System.out.println("数组扩大二倍后打印");
        System.out.println(Arrays.toString(ret));
        System.out.println(Arrays.toString(array));
    	}
    public static int[] fun(int[] array){
    
    
        for (int i = 0;i < array.length;i++){
    
    
            array[i] = array[i] * 2;
        }
        return array;
    }
}

运行结果如下
在这里插入图片描述
可见,修改了原数组。
将原来数组的值,扩大二倍。不改变原数组。

import java.util.*;

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] array = {
    
    1,2,3,4,5};
        System.out.println("数组扩大二倍前打印");
        System.out.println(Arrays.toString(array));
        int[] ret = fun(array);
        System.out.println("数组扩大二倍后打印新数组");
        System.out.println(Arrays.toString(ret));
        System.out.println("数组扩大二倍后,打印原数组");
        System.out.println(Arrays.toString(array));
        }
    public static int[] fun(int[] array){
    
    
        int[] ret = new int [array.length];
        for (int i = 0;i < array.length;i++){
    
    
            ret[i] = array[i] * 2;
        }
        return ret;
    }
}

运行结果如下
在这里插入图片描述
可见,未修改原数组。

这两个代码的区别在于,是否改变原数组。
这就是典型的数组作为方法的返回值。

数组练习

数组转字符串

这道题,在这一期前面的内容有写过,非常之简单。

import java.util.*;

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] array = {
    
    1,2,3,4,5,6};
        String ret = Arrays.toString(array);
        System.out.println(ret);
    }
}

执行结果
在这里插入图片描述

Java 中提供了 java.util.Arrays 包,其中包含了一些操作数组的常用方法。
用自己的方法如下

import java.util.*;

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] array = {
    
    1,2,3,4,5};
        //String ret = Arrays.toString(array);
        System.out.println(toString(array));
    }
    public static String toString(int[] array){
    
    
        String ret = "[";
        for (int i = 0;i <array.length;i++){
    
    
            ret += array[i];
            if (i != array.length-1){
    
    
                ret += ",";//各元素之间需要添加‘,’
            }
        }
        ret += "]";
        return ret;
    }
}

执行结果
在这里插入图片描述

数组拷贝

import java.util.*;

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] array1 = {
    
    1,2,3,4,5};
        int[] array2 = new int[array1.length];
        System.out.println("拷贝完成前,打印数组array1");
        System.out.println(Arrays.toString(array1));
        System.out.println("拷贝完成前,打印数组array2");
        System.out.println(Arrays.toString(array2));
        System.out.println("=========================");
        for (int i = 0;i < array1.length;i++){
    
    
            array2[i] = array1[i];
        }//方法一
        
        /* array2 = Arrays.copyOf(array1,array1.length);
        //使用操作数组工具类
        //方法二
         */
        /*System.arraycopy(array1,0,array2,0,array1.length);
        方法三
         */
        /*array2 = array1.clone();
        方法四
         */
        System.out.println("拷贝完成后,打印数组array1");
        System.out.println(Arrays.toString(array1));
        System.out.println("拷贝完成后,打印数组array2");
        System.out.println(Arrays.toString(array2));
        //四种方法其中方法三最快。
        System.out.println("=========================");
        array2[0] = 99;
        System.out.println("修改array2后,打印数组array1");
        System.out.println(Arrays.toString(array1));
        System.out.println("修改array2后,打印数组array2");
        System.out.println(Arrays.toString(array2));
        //拷贝后修改array2数组的值,array1数组不发生改变。
    }
}

运行结果如下(其中四种方法的运行结果均相同)
在这里插入图片描述
只拷贝某个范围。

import java.util.*;

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] array1 = {
    
    1,2,3,4,5};
        int[] array2 = new int[array1.length];
        array2 = Arrays.copyOfRange(array1,2,5);
        System.out.println(Arrays.toString(array2));
        // 范围拷贝
    }
}

执行结果
在这里插入图片描述

找数组中的最大元素

import java.util.*;

public class TextDemo {
    
    

    public static void main(String[] args) {
    
    
        int[] arr = {
    
    12,21,33,24,45,16};
        System.out.println(max(arr));
    }
    public static int max(int[] arr) {
    
    
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
    
    
            if (arr[i] > max) {
    
    
                max = arr[i];
            }
        }
        return max;
    }
}

执行结果
在这里插入图片描述

求数组中元素的平均值

import java.util.*;

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    1,2,3,4,5,6,7};
        System.out.println(avg(arr));
    }
    public static double avg(int[] arr) {
    
    
        int sum = 0;
        for (int x : arr) {
    
    
            sum += x;
        }
        return (double)sum / (double)arr.length;
    }
}

执行结果
在这里插入图片描述

查找数组中指定元素(顺序查找)

import java.util.*;

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    21,12,3,81,59,36};
        System.out.println(find(arr, 81));
    }
    public static int find(int[] arr, int toFind) {
    
    
        for (int i = 0; i < arr.length; i++) {
    
    
            if (arr[i] == toFind) {
    
    
                return i;
            }
        }
        return -1; // 表示没有找到
    }
}

执行结果
在这里插入图片描述

查找数组中指定元素(二分查找)

针对有序数组,可以使用更高效的二分查找。

import java.util.*;

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    1,2,3,4,5,6};
        System.out.println(binarySearch(arr, 6));
    }
    public static int binarySearch(int[] arr, int toFind) {
    
    
        int left = 0;
        int right = arr.length - 1;
        while (left <= right) {
    
    
            int mid = (left + right) / 2;
            if (toFind < arr[mid]) {
    
    
                // 去左侧区间找
                right = mid - 1;
            } else if (toFind > arr[mid]) {
    
    
                // 去右侧区间找
                left = mid + 1;
            } else {
    
    
                // 相等, 说明找到了
                return mid;
                }
            }
            // 循环结束, 说明没找到
        return -1;
    }
}

执行结果
在这里插入图片描述

检查数组的有序性

import java.util.*;

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    1,2,3,10,5,6};
        System.out.println(isSorted(arr));
    }
    public static boolean isSorted(int[] arr) {
    
    
        for (int i = 0; i < arr.length - 1; i++) {
    
    
            if (arr[i] > arr[i + 1]) {
    
    
                return false;
            }
        }
        return true;

执行结果
在这里插入图片描述

数组排序(冒泡排序)

冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。
它重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从大到小、首字母从Z到A)错误就把他们交换过来。走访元素的工作是重复地进行直到没有相邻元素需要交换,也就是说该元素列已经排序完成。

import java.util.*;

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] array = {
    
    9, 9, 8, 1};
        bubbleSort(array);
        System.out.println(Arrays.toString(array));
    }

    public static void  bubbleSort(int[] arr){
    
    
        for (int i = 0; i < arr.length; i++) {
    
    
            for (int j = arr.length - 1; j > i; j--) {
    
    
                if (arr[j - 1] > arr[j]) {
    
    
                    int temp = arr[j - 1];
                    arr[j - 1] = arr[j];
                    arr[j] = temp;
                }
            }
        }
    }
}

执行结果
在这里插入图片描述

Java中,实现数组排序可以使用操作数组工具类。代码如下

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    3, 2, 5, 1};
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
    }
}

执行结果
在这里插入图片描述

数组逆序

给定一个数组,将里面的元素逆序排列。
思路
设定两个下标, 分别指向第一个元素和最后一个元素. 交换两个位置的元素.
然后让前一个下标自增, 后一个下标自减, 循环继续即可。

import java.util.*;

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] arr = {
    
    1, 2, 3, 4,5,6,7,8,9};
        reverse(arr);
        System.out.println(Arrays.toString(arr));
    }
    public static void reverse(int[] arr) {
    
    
        int left = 0;
        int right = arr.length - 1;
        while (left < right) {
    
    
            int tmp = arr[left];
            arr[left] = arr[right];
            arr[right] = tmp;
            left++;
            right--;
        }
    }
}

执行如下
在这里插入图片描述

数组数字排列

给定一个整型数组,将所有的偶数放在前半部分,将所有的奇数放在数组后半部分。代码如下:

import java.util.*;

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[] array = {
    
    1, 2, 3, 4, 5, 6,7,8};
        transform(array);
        System.out.println(Arrays.toString(array));
    }
    public static void transform(int[] arr) {
    
    
        int left = 0;
        int right = arr.length - 1;
        while (left < right) {
    
    
            // 该循环结束, left 就指向了一个奇数

            while (left < right && arr[left] % 2 == 0) {
    
    
                left++;
            }
            // 该循环结束, right 就指向了一个偶数
            while (left < right && arr[right] % 2 != 0) {
    
    
                right--;
            }
            int temp = arr[left];
            arr[left] = arr[right];
            arr[right] = temp;
        }
    }
}

执行结果
在这里插入图片描述

二维数组

二维数组本质上也就是一维数组,只不过每个元素又是一个一维数组。
在这里插入图片描述

基本语法

数据类型[][] 数组名称 = new 数据类型 [行数][列数] {
    
     初始化数据 };

我们用打印一个二维数组作为示例,代码如下:

import java.util.*;

public class TextDemo {
    
    
    public static void main(String[] args) {
    
    
        int[][] array = {
    
    
                {
    
    1,2,3,4},
                {
    
    5,6,7,8},
                {
    
    9,10,11,12},
        };
        for (int row = 0; row < array.length; row++) {
    
    
            for (int col = 0; col < array[row].length; col++) {
    
    
                System.out.printf("%d\t", array[row][col]);
            }
            System.out.println("");
        }
    }
}

执行结果
在这里插入图片描述
二维数组的用法和一维数组并没有明显差别,因此我们不再赘述。
同理,还存在 “三维数组”,“四维数组” 等更复杂的数组, 只不过出现频率都很低,很少用到。

Java入门(四)之 数组的定义与使用,到这里就基本结束了。
下期带来Java入门(五)之 类和对象。各位铁铁,我们下期见。

猜你喜欢

转载自blog.csdn.net/Kaiiiiiiiiiiiiii/article/details/112397463