数组(Array)

数组

数组的概述&数组的内存分析

之前我们在定义数据的时候,基本上都是用变量来存储数据。但是如果我们的程序中出现大量的数据该怎么办?比如连续输入多个数字,连续输入多个坐标点,对于这种一般而言计算机会创建多个变量来存储这些数据,虽然没有问题,但是显得比较麻烦。我们通过观察可以发现,这些变量基本上类型是共通的,那我们就可以用一个容器将所有的数据进行管理,这类似于字符串,字符串其实就是若干个字符的容器而已,“abc”可以通过索引/角标来获取其中某一个字符,[1,2,3,4,5]类似字符串也能够通过索引/角标来获取其中某一个数字,这个容器我们称之为数组。数组主要解决多变量多数据的存储问题,这方便程序后期统一维护操作数据。

说了这么多关于数组的概述,那么数组的本质到底是什么呢?其实,数组就是一系列空间大小相等且地址连续的一片存储空间。空间大小相等是为了方便统一维护我们的数据,必须得保证数据之间的类型是一样的(多个同类型的变量空间连在一起组成的结构叫数组);至于变量空间地址连续则是为了方便统一操作我们的数据(见下面的数组内存图)。

  •  数组的定义&数组的常见错误

数组就是一片地址连续且空间大小一致的存储空间(但是每个空间存的还是其他数据的地址),数组存在于堆内存中,但凡在堆中存储的数据都称之为对象,但凡在堆内存中创建的对象都会有默认初始值,整数类型默认0,浮点类型默认0.0,布尔类型默认false,引用数据类型(对象)默认null。

关于数组的一些注意事项:

1.数组变量存的就是数组在堆内存中首元素的地址;

2.数组提供角标来访问数组当中的元素,数组通过角标来访问元素的具体计算方式是:所要访问数据的地址 = 首元素地址+角标*数据类型大小;

3.数组一旦定义下来,其长度不可改变。数组中有几个地址?就看数组有几个元素空间<==>数组的长度。

数组的创建:数组创建时必须明确规定大小或内容

1. 数据类型[ ] 数组名 = new 数据类型[长度]   创建数组只指定长度但不指定内容

2. 数据类型[ ] 数组名 = new 数据类型[ ]{1,2,3,4,5}    创建数组指定内容(指定长度)

3. 数据类型[ ] 数组名 = {1,2,3,4,5}   创建数组指定内容(指定长度)

此外 [ ]表示是一维数组,[ ][ ]表示是二维数组。

来看个例子:

class Test04{
    public static void main(String[] args){
        //1.创建长度为5的String型数组
        String[] strArr = new String[5];
	//访问strArr数组中第1个元素
        System.out.println(strArr[0]);
		
	//2.创建长度为5的int型数组
        int[] arr = new int[5];
        //访问arr数组中第4个元素
        System.out.println(arr[3]);
		
        //这个输出语句是访问arr中第11个元素,但因为arr数组的长度只有5,                           
        //所以会出错。错误是"ArrayIndexOutOfBoundsException角标越界"      
	//System.out.println(arr[10]);
		
        //新创建一个变量arr2指向原来的数组,此时数组还是
        //那个数组对象,只不过有两个变量引用到了而已。
        int[] arr2 = arr;
        arr2[0] = 10;
        System.out.println(arr[0]);//10
        arr2 = null;
        //System.out.println(arr2[0]);arr2为空,所以出错NullPointerException空指针异常
		
        arr = null;
        //此时此刻,数组对象没有任何变量引用它
        //数组对象在堆内存中就没有存在的意义了
        //所以该对象变成垃圾,由【垃圾回收器gc】处理
        //【垃圾回收器】是JVM中的一个程序,专门用于负责处理堆内存中垃圾数据的。
        //垃圾的处理并不是及时的,由【gc】来控制,当垃圾堆攒到一定程度时由【gc】来处理
        //特殊的在C/C++中,如果出现对象垃圾,必须程序员手动处理,借助free()及时处理
    }
}

如上述代码所述,数组中常见的错误有两种,一个是"ArrayIndexOutOfBoundsException角标越界",一个是"NullPointerException空指针异常",所以我们写代码的时候要特别注意不要发生这两种错误。另外,当把一个数组变为null后,此时也就没有任何变量去引用它,数组对象在内存中也没有存在意义,所以会被垃圾回收器回收。

  • 基本数组操作

一般有求最大值、最小值,对数组进行遍历,对数组进行赋值等,具体都写在代码中了。

import java.util.*;
class Test05{
    public static void main(String[] args){
        //求最大值、最小值操作
        maxormin();

        //赋值操作
        fuzhi();

        //遍历操作
        bianli();        
    }
    //求最大值、最小值操作
    public static void maxormin(){
        //计算最大值或最小值的 值
        //计算最大值或最小值的 角标
        //需求:获取最大值10,获取最小值的角标4
        int[] arr={10,2,8,3,1,6,4,7,9,5};
        int max=arr[0];
        int min_index=0;
        for(int i=0;i<arr.length;i++){
            if(arr[i]>max){
                max=arr[i];
            }
            if(arr[i]<arr[min_index]){
                min_index=i;
            }
        }
        System.out.println("最大值"+max);//最大值10
        System.out.println("最小值角标"+min_index);//最小值角标4

    }
    //赋值操作
    public static void fuzhi(){
        Scanner scanner = new Scanner(System.in);
        //System.out.print("请输入10个数字:");
        int[] arr2 = new int[10];
        for(int i=0;i<arr2.length;i++){
            System.out.print("请输入1个数字:");
            arr2[i] = scanner.nextInt();
        }
        for(int i=0;i<arr2.length;i++){
            System.out.print(arr2[i]+" ");
        }
    }
    //遍历操作
    public static void bianli(){
        int[] arr={1,2,3,4,5,6,7,8,9};//[0,8]
        //数组只有一个唯一的属性length,数组的长度
        System.out.println(arr.length);
        for(int i=0;i<arr.length;i++){
            System.out.println(arr[i]);
        }
    }
}
  • 查找操作

查找操作这里就说一下二分查找和线性查找,具体操作都写在代码中了。

class Test06{
    public static void main(String[] args){
        //线性查找
        linearSearch();
		
        //二分查找
        binarySearch();
    }
    public static void binarySearch(){
        //二分查找有个前提,数组必须有序
        /* 
        最好情况 查46    1次就出来了
        最坏情况 查12/60 O(logn)
        */
        int[] arr = {12,17,21,32,38,41,46,49,50,50,51,59,60};
        int key = 46;
        int index = -1;
        int min_index = 0;
        int max_index = arr.length - 1;
        int mid_index = (min_index + max_index) / 2;
        while(arr[mid_index]!=key){
            if(key < arr[mid_index]){
                max_index = mid_index-1;
            }
            if(arr[mid_index] < key){
                min_index = mid_index+1;
            }
            if(min_index > max_index){
                index = -1;
                break;
            }
            mid_index = (min_index + max_index) / 2;
        }
        System.out.println(mid_index);

    }
    public static void linearSearch(){
        /* 
        最好情况 查10 1次就出来了
        最坏情况 查5  10次才出来
        当数组的长度越大的话,最坏情况越差
        时间复杂度(最坏情况)为O(n),是线性阶
        */
        int[] arr={10,2,8,3,1,6,4,7,9,5};
        int key=8;//2
        int key=11;//-1
        int index=-1;//默认是-1,如果返回角标是-1则说明key元素不存在于数组当中
        for(int i=0;i<arr.length;i++){
            if(arr[i]==key){
                index=i;
                break;
            }
        }
        System.out.println(index);
    }
}
  •  数组的扩容

数组的扩容,就是创建一个新的数组,然后将元素赋值进去,最后将新数组的地址返回即可。

class Test01{
    /* 
    数组的扩容,无非就是创建一个新的数组 将元素赋值进去之后
    将新数组的地址返回即可
    */
    public static void main(String[] args){
        int[] arr = new int[]{1,2,3};
        arr = copyOf(arr,arr.length+1);//扩容
        arr[arr.length-1] = 10;
        System.out.println(arr[3]);
    }
    public static int[] copyOf(int[] arr,int newLen){
        int[] newArr = new int[newLen];
        for(int i = 0;i < arr.length;i++){
            newArr[i] = arr[i];
        }
        return newArr;
    }
}

首先我们定义了一个整型的数组arr,长度为3。如果我们要访问arr[3],即就是访问arr数组中第四个元素的话,就会出错,这个时候就需要用到copyOf来对数组进行扩容,对数组增加一个长度。通过调用copyOf函数将arr数组的长度扩充,copyOf函数中,传进来的参数分别是之前的arr数组(地址)、新的长度。定义一个新的数组newArr,然后将arr数组中的所有元素都给newArr,最后返回newArr,将新数组的地址返回,再对arr[3]进行赋值、输出。

  • 二维数组

简单来说就是一个由行和列组成的一个表格而已,如果每行的元素长度相等,也可以看作是一个矩阵(Matrix)。在二维数组中访问元素的话,是根据元素的行角标和列角标来访问的。那么二维数组是在内存中具体是如何存储的呢?其实无论是二维数组,还是多维数组,它们本身就是一个一维数组,尤其对于二维数组而言,它无非就是一个一维数组,只不过该一维数组中的每一个元素是另一个一维数组而已。所以它跟一维数组的存储方式一样,都是在堆中存储的。

二维数组的表示方法:

1. int[ ][ ]  matrix = new int[3][4];     创建一个3行4列的二维数组,元素默认都是0。

2. int[ ][ ] matrix = new int[ ][ ]{                创建一个指定元素的二维数组。
               {1,2,3,4} ,
               {5,6,7,8} ,
               {9,10,11,12} 
           };

3. int[][] matrix={          创建一个指定元素的二维数组,最简单的创建方式。
               {1,2,3,4} ,
               {5,6,7,8} ,
               {9,10,11,12} 
           };

关于上面创建的二维数组,请看下面这幅图:

很直观明了,相信大家一看就懂!好了,关于数组的内容我们就说到这里!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值