Java数组

目录

 数组的基本概念

1.为什么要使用数组

2.什么是数组

3.数组的创建及初始化

 数组的创建

 数组的初始化

4.数组的使用

数组中元素的访问

遍历数组 

5. 数组是引用类型

 初始JVM的内存分布

基本类型变量与引用类型变量的区别

认识null 

6.数组的应用场景

保存数据 

作为函数参数 

 作为函数的返回值

7.数组练习 

数组拷贝

求数组中元素的平均值

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

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

Arrays工具的查找方法

数组排序(冒泡排序)

 Arrays工具的进行排序

 数组逆序

8.一些Arrays工具的介绍 

 比较数组Arrays.equals

填充数组 Arrays.toString

9. 二维数组


 数组的基本概念

数组可以理解成一个小盒子,里面可以装若干个同类型的元素,每个元素都有唯一的编号(或者标识符)

1.为什么要使用数组

     假设有这样一个场景,我们要存放5个学生的考试成绩,我们很快就能写出一个代码,用5个变量分别存放就好了,可是如果有100个学生,或者更多呢?我们难道要100个变量吗? 

    通过观察这些学生的成绩,数据类型都是一样的,在java中的数组,就可以把这些相同类型的数组存放起来 ,那数组是什么,该怎么去使用呢?请看下文。

2.什么是数组

 数组:可以看成是相同类型元素的一个集合。在内存中是一段连续的空间。比如现实中的车库:

Java数组_第1张图片

从上图中可以看到:

 1. 数组中存放的元素其类型相同
 2. 数组的空间是连在一起的
 3. 每个空间有自己的编号,其实位置的编号为0,即数组的下标

3.数组的创建及初始化

 数组的创建

T[] 数组名 = new T[N];

 T:表示数组中存放元素的类型
 T[]:表示数组的类型
 N:表示数组的长度

 int[] array1 = new int[10];   //创建了一个可以容纳10个int类型的数组
 double[] array2 = new double[5]; //创建一个可以容纳5个double类型的数组
 String[] array3 = new String[3]; //创建了一个可以容纳3个字符串类型的数组

 数组的初始化

 1. 动态初始化:在创建数组时,直接指定数组中元素的个数

int[] array = new int[10] ;

 2. 静态初始化:在创建数组时不直接指定数据元素个数,而直接将具体的数据内容进行指定

 语法格式:T[] 数组名称 = {data1, data2, data3, ..., datan};

 int[] array1 = new int[]{1,2,3,4,5};
 int[] array2 = {1,2,3,4,5};

【注意事项】 

 静态初始化虽然没有指定数组的长度,编译器在编译时会根据{}中元素个数来确定数组的长度。
 静态初始化时, {}中数据类型必须与[]前数据类型一致。

也可以分成两步

 int[] array ;
 array = new int[]{1,2,3,4,5};

如果没有对数组进行初始化,数组中元素还有其默认值

 如果数组中存储元素类型为基类类型,默认值为基类类型对应的默认值,比如、、

Java数组_第2张图片

 如果数组中存储元素类型为引用类型,默认值为null

4.数组的使用

数组中元素的访问

数组在内存中是一段连续的空间,下标从零开始,依次递增,通过下标可以访问数组的任意元素。

Java数组_第3张图片

【注意事项】

下标从0开始,介于【0,N  之间不包含N,N为元素个数,不能越界,否则会报错。

Java数组_第4张图片

抛出了 java.lang.ArrayIndexOutOfBoundsException 异常. 使用数组一定要下标谨防越界
 

遍历数组 

方法一

所谓 "遍历" 是指将数组中的所有元素都访问一遍, 访问是指对数组中的元素进行某种操作,比如:打印。
通过循环来遍历数组就好了,在数组中可以通过数组对象.length 来获取数组的长度

Java数组_第5张图片

方法二 

通过for-each 遍历数组,for-each是循环的增强版

Java数组_第6张图片
 语法格式for(数据类型:数组名

注意:这种方式是适合用来遍历数组 

方法三

 通过Arrays实现

Java数组_第7张图片

Arrays是一个操作数组的一个工具类(一个功能非常强大的工具),toSting是这个工具提供的一个方法,他的作用是将数组转换成字符串并且打印。 

5. 数组是引用类型

 初始JVM的内存分布

 java当中的内存划分是什么样子的呢?JVM当中的内存划分。

Java数组_第8张图片

   通过上图可以看到可以分为5个区,划分区域是让我们更好的去管理内存,每一个区都有他自己的独特的功能。

基本类型变量与引用类型变量的区别

基本数据类型创建的变量,称为基本变量,该变量空间中直接存放的是其所对应的值;
而引用数据类型创建的变量,一般称为对象的引用,其空间中存储的是对象所在空间的地址


如果有这样一段代码他们在内存中是怎样存放的呢?

public static void func() {
    int a = 10;
    int b = 20;
    int[] arr = new int[]{1,2,3};
}

 a和b为基本变量,是存放在栈上的,arr为引用变量虽然也在栈上,但是内部存放的是数组在堆上的地址。

Java数组_第9张图片

从上图可以看到,引用变量并不直接存储对象本身,可以简单理解成存储的是对象在堆中空间的起始地址。通过该地址,引用变量便可以去操作对象。有点类似C语言中的指针,但是Java中引用要比指针的操作更简单
 

认识null 

null在java中表示“空引用”

注意这样的代码是一定会报一个空指针异常的错误的。

Java数组_第10张图片

 null 的作用类似于 C 语言中的 NULL (空指针), 都是表示一个无效的内存位置.

6.数组的应用场景

保存数据 

public static void main(String[] args) {
    int[] array = {1, 2, 3};
    for(int i = 0; i < array.length; ++i){
         System.out.println(array[i] + " ");
    }
}

作为函数参数 

 传基本数据类型

Java数组_第11张图片

Java数组_第12张图片  

通过观察修改形参x的值,不影响实参的值,因为这是两个没有任何关系的值。

传数组类型(引用类型)

Java数组_第13张图片 发现在func方法内部修改数组的内容, 方法外部的数组内容也发生改变.
因为数组是引用类型,按照引用类型来进行传递,是可以修改其中存放的内容的。

Java数组_第14张图片

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

 作为函数的返回值

java中的数组是可以作为函数的返回值的,比如:获取斐波那契数列的前N项

Java数组_第15张图片

7.数组练习 

数组拷贝

方法一   

  newArr和arr引用的是同一个数组
 因此newArr修改空间中内容之后,arr也可以看到修改的结果

 public static void main(String[] args) {
        int[] arr = {1,2,3,4,5};
        int[] newarr = arr;
        System.out.println("newArr: " + Arrays.toString(newarr));
 }

方法二: 

 使用Arrays中copyOf方法完成数组的拷贝

 public static void main(String[] args) {
        int[] arr = {1,2,3,4,5};
        int[] newarr;
        newarr = Arrays.copyOf(arr,arr.length);
        System.out.println(Arrays.toString(newarr));
 }

copyOf使用方法:copyOf(原数组:数组长度)

方法三 

拷贝某个范围

使用Arrays中copyOfRange方法完成数组的拷贝

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

 copyOfRange使用方法:copyOfRange(原数组:数组范围),范围是一个左闭右开的区间。

方法四 

实现自己版本的拷贝数组

 public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        int[] newarr = new int[5];
        for (int i = 0; i < arr.length; i++) {
            newarr[i] = arr[i];
        }
        System.out.println(Arrays.toString(newarr));
 }

求数组中元素的平均值

这个代码比较简单,只需要把所有元素加起来除以数组长度即可。

   public static void main(String[] args) {
        int[] arr = {1,2,3,4,5};
        double sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum+=arr[i];
        }
        double avg = sum / (arr.length) ;
        System.out.println(avg);
  }

需要注意的是要用浮点型。

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

 给定一个数组, 再给定一个元素, 找出该元素在数组中的位置.

 代码示例

    public static int find(int[] array , int n){
        for (int i = 0; i < array.length; i++) {
            if(array[i] == n){
                return i;
            }
        }
        return -1;
    }

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

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

 以升序数组为例, 二分查找的思路是先取中间位置的元素, 然后使用待查找元素与数组中间元素进行比较:

  1.  如果相等,即找到了返回该元素在数组中的下标
  2.  如果小于,以类似方式到数组左半侧查找
  3.  如果大于,以类似方式到数组右半侧查找
    public static int binarySearch(int[] array ,int n){
        int i = 0;
        int j = array.length-1;
        while (i <= j){
            int mid = (i+j)/2;
            if(array[mid]>n){
                j = mid - 1;
            } else if (array[mid]

可以看到, 针对一个长度为 10000 个元素的数组查找, 二分查找只需要循环 14 次就能完成查找. 随着数组元素个数越多, 二分的优势就越大

Arrays工具的查找方法

 使用方法Arrays.binarySearch(查找的数组名 , 需要查找的值)

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.print("请输入你要找的值>: ");
        int x  = sc.nextInt();
        int[] arr = {1,2,3,4,5};
        int ret = Arrays.binarySearch(arr,x);
        System.out.println(ret);
    }

数组排序(冒泡排序)
 

给定一个数组, 让数组升序 (降序) 排序.
算法思路
假设排升序:
1. 将数组中相邻元素从前往后依次进行比较,如果前一个元素比后一个元素大,则交换,一趟下来后最大元素就在数组的末尾
2. 依次从上上述过程,直到数组中所有的元素都排列好
代码示例

    public static void main(String[] args) {
        int[] arr = {10,9,8,7,6,5,4,3,2,1};
        for (int i = 0; i < arr.length-1; i++) {
            for (int j = 0; j < arr.length-1-i; j++) {
                 if(arr[j]>arr[j+1]){
                     int tmp = arr[j];
                     arr[j] = arr[j+1];
                     arr[j+1] = tmp;
                 }
            }
        }
        System.out.println(Arrays.toString(arr));
    }

 Arrays工具的进行排序

    public static void main(String[] args) {
        int[] arr = {10,9,8,7,6,5,4,3,2,1};
        Arrays.sort(arr);
        System.out.println(Arrays.toString(arr));
    }

 数组逆序

给定一个数组, 将里面的元素逆序排列

    public static void main(String[] args) {
        int[] arr = {10,9,8,7,6,5,4,3,2,1};
        int i = 0;
        int j = arr.length-1;
        while (i

8.一些Arrays工具的介绍 

 比较数组Arrays.equals

    public static void main(String[] args) {
        int[] arr = {1,2,3};
        int[] arrs = {1,2,3};
        System.out.println(Arrays.equals(arr, arrs));
    }

 里面的参数是要比较的两个数组,如果一样会返回ture,不一样会返回false

填充数组 Arrays.toString

    public static void main(String[] args) {
        int[] arr = new int[10];
        Arrays.fill(arr,99);
        System.out.println(Arrays.toString(arr));
    }

 这个代码会给数组的每个元素赋值为99

也可以范围填充

Java数组_第16张图片

9. 二维数组

二维数组本质上也就是一维数组, 只不过每个元素又是一个一维数组


 基本语法

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

    int[][] arr1 = {{1,2,3},{4,5,6},{7,8,9}};
    int[][] arr2 = new int[3][3];

Java数组_第17张图片 

代码示例

    public static void main(String[] args) {
        int[][]arr = {{1,2,3},{4,5,6},{7,8,9}};
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[1].length; j++) {
                System.out.print(arr[i][j]+" ");
            }
            System.out.println();
        }
    }

可以通过deepToString来进行打印

    public static void main(String[] args) {
        int[][] arr1 = {{1,2,3},{4,5,6},{7,8,9}};
        System.out.println(Arrays.deepToString(arr1));
    }

 java当中还支持不规则数组,就是每一行的元素个数不一样

二维数组的用法和一维数组并没有明显差别, 因此我们不再赘述
 

到这里就结束啦! 喜欢的记得点个赞,有问题可以打在评论区。 

你可能感兴趣的:(java)