java的数组

概念

概念:一组连续的存储空间,存储多个相同数据类型的值
特点:
    类型相同
    长度固定

声明与赋值

格式:
数据类型[] 变量名=new 数据类型[长度];
eg:int[] a=new int[5];

数组的默认值:int=0,String=null,根据数据类型而定

创建方式

   1. 先声明再分配空间:int [] array;    array=new int[9];
   2. 声明并分配空间:int[] a=new int[5];
   3. 声明并赋值(繁):int[] a=new int{1545};
   4. 声明并赋值(简):int [] a={1,2,5,6,7};

赋值:

    public static void main(String[] args) {
        int[] a=new int[5];
        a[0]=10;
        a[1]=20;
        a[2]=30;
        a[3]=40;
        a[4]=50;
        System.out.println(a[0]);
        System.out.println(a[1]);
        System.out.println(a[2]);
        System.out.println(a[3]);
        System.out.println(a[4]);
    }

如果访问a[5],就会提示数组下表越界报错:

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5

默认值

整数型 : byte short int long 默认初始化值都是0
浮点型 : float double 默认初始化值都是0.0
布尔型 : boolean 默认初始化值是false
字符型 : char 默认初始化值是 ‘\u0000’ ⼗六进制的
引⽤数据类型 : 所有引⽤数据类型的初始化值都是null

组成

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dJV8c9pu-1645534171747)(file://F:\WP\BaiduNetdiskWorkspace\noteFile\JavaSE\5、数组\数组.assets\20210811191509454_2498.png?lastModify=1631452967)]

内存模型

Java程序在运⾏的时候, Java虚拟机运⾏程序,必须要对内存进⾏空间的分配和管理。内存是计算机中的重要原件,临时存储区域,作⽤是运⾏程序。

内存划分:

  • 寄存器 Registers
    速度最快的存储场所,处于处理器的内部,个数优先,编译器根据需求分配,不能通过代码控制
  • 本地⽅法区 Native Method
    保存native⽅法进去区域的地址
  • ⽅法区 Method
    ⼜称为静态区,是程序中永远唯⼀的元素存储区域。
    ⽤于存储已经被虚拟机加载的类信息、常量、静态变量、静态⽅法、成员⽅法等即使编译器编译后的代码被所有的线程共享
  • 栈内存 Stack
    ⽤于存储局部变量,当变量所属的作⽤域⼀旦结束,所占⽤的空间会⽴刻释放
    ⽤于存放被引⽤的对象和基本的数据类型对象
    速度仅次于寄存器
  • 堆内存 Heap
    数组和对象,通过new简历的实例颤抖存放在堆内存中
    每个实体都有内存地址值
    实例中的变量都有默认初始化值,根据类型的不同⽽不同
    如果将数组中的引⽤实体设置为null,也就是实体不再被使⽤,那么在不确定的时间内被垃圾回收期回收
区域名称作用
寄存器给CPU使用,和我们开发无关
本地方法区JVM在使用操作系统功能的时候使用,和开发无关
方法区存储可以运行的class文件
堆内存存储对象或者数组,new创建出来的,都存储到堆内存中
栈内存方法运行时使用的内存

数组在内存中的处理

  1. 仅仅声明数组的时候,会在栈中开辟⼀个空间给刚创建出的数组,对应的值是null,⽽不会在堆中做任何的处理

  1. 数组的初始化,其实就是声明数组之后,在堆内存中对于数组进⾏处理。

    堆内存中将数组的元素按照顺序开辟连续的内存空间存储,然后将第⼀个元素的地址赋给栈内存中数组对应
    的变量,以便于在栈内存中寻找到。这也就是引⽤类型,传递的是引⽤和地址,也可以理解成数组变量执⾏的
    内存地址
    所以所谓的初始化,就是为数组开辟连续的内存空间,并未每个数组赋值

遍历

for循环遍历

    public static void main(String[] args) {
        int[] a=new int[5];
        a[0]=10;
        a[1]=20;
        a[2]=30;
        a[3]=40;
        a[4]=50;
       for (int i=0;i<a.length;i++){
           System.out.println(a[i]);
       }
    }

使用.length动态获取数组长度

获取最大值

public static int getMax(int[] arr){
    //定义存储最⼤值的变量
    int max = arr[0];
    for (int i = 1; i < arr.length; i++) {
        if(arr[i] > max){
            max = arr[i];
        }
    }
    return max;
}

反转数组

实现思路:数组最远端的元素互换位置。
实现反转,就需要将数组最远端元素位置交换
定义两个变量,保存数组的最⼩索引和最⼤索引
两个索引上的元素交换位置
最⼩索引++,最⼤索引–,再次交换位置
最⼩索引超过了最⼤索引,数组反转操作结束

public static void reverse(int[] arr){
    //数组中的元素前后交换, 遍历的次数只能是数组⻓度的⼀半
    for (int i = 0; i < arr.length/2; i++) {
        int temp = arr[i];
        arr[i] = arr[arr.length-i-1];
        arr[arr.length-i-1] = temp;
    }
}
public static void main(String[] args) {
    int[] arr = { 1, 2, 3, 4, 5 };
    /* 循环中定义变量min=0最⼩索引 max=arr.length‐1最⼤索引 min++,max‐*/
    for (int min = 0, max = arr.length ‐ 1; min <= max; min++, max‐‐) {
        //利⽤第三⽅变量完成数组中的元素交换
        int temp = arr[min]; arr[min] = arr[max]; arr[max] = temp;
    }
    // 反转后,遍历数组
    for (int i = 0; i < arr.length; i++) {
        System.out.println(arr[i]);
    }
}

第一次出现的位置

public static int indexOf(int[] arr,int value){
    //数组中的元素前后交换, 遍历的次数只能是数组⻓度的⼀半
    for (int i = 0; i < arr.length; i++) {
        if (arr[i]==value) {
        return i;
        }
    }
    return -1;
}

排序

冒泡排序

相邻的两个值⽐较, 然后交换位置, 每次循环都会将有效元素中最⼤的或最⼩的移动到有效位的最后,经过多次循环之后,就可以排出⼀个有序的数组

private static void BubbleSortDemo() {
    int[] nums = {50, 32, 52, 39, 38, 51, 31, 10, 51, 13, 25, 5};
    System.out.println("原数组:" + Arrays.toString(nums));
    //排序的次数
    for (int i = 1; i < nums.length; i++) {
        //找数据:大小
        for (int j = 0; j < nums.length - i; j++) {
            if (nums[j] > nums[j + 1]) {
                int temp = nums[j];
                nums[j] = nums[j + 1];
                nums[j + 1] = temp;
            }
        }
    }
    System.out.println("冒泡排序:" + Arrays.toString(nums));
    System.out.println();
}

选择排序

算法思想:选择排序,从头⾄尾扫描序列,找出最⼩的⼀个元素,和第⼀个元素交换,接着从剩下的元素中继
续这种选择和交换⽅式,最终得到⼀个有序序列。

推理过程

	private static void eww() {
        int[] nums = {50, 32, 52, 39, 38, 51, 31, 10, 51, 13, 25, 5};
        int index = 0;
        for (int i = 0; i < nums.length - 1; i++) {
            if (nums[index] < nums[i + 1]) {
                index = i + 1;
            }
        }
        System.out.println(index);
        if (index != nums.length - 1) {
            int temp = nums[nums.length - 1];
            nums[nums.length - 1] = nums[index];
            nums[index] = temp;
        }
        System.out.println("原数组:" + Arrays.toString(nums));

总结

private static void ChooseSortDemo() {
    int[] nums = {50, 32, 52, 39, 38, 51, 31, 10, 51, 13, 25, 5};
    System.out.println("原数组:" + Arrays.toString(nums));

    for (int i = 0; i <nums.length ; i++) {
        int index=0;
        for (int j = 1; j <nums.length-i ; j++) {
            if (nums[index]>nums[j]){
                index=j;
            }
        }
        if (index!=nums.length-1-i){
            int temp=nums[index];
            nums[index]= nums[nums.length-1-i];
            nums[nums.length-1-i]=temp;
        }
    }
    System.out.println("选择排序:" + Arrays.toString(nums));
}

JDK排序

排序:升序

    public static void main(String[] args) {
        int[] num = {11, 55, 19, 56, 14};
        //借助arrays类的sort方法实现数组的升序
        Arrays.sort(num);
        //遍历输出
        for (int i = 0; i < num.length; i++) {
            System.out.println(num[i]);
        }
        
        System.out.println();
        
        //降序:
        //将之前升序的数组倒置,第一个和最后一个,第二个和倒数第二个。
        //i <= num.length / 2是循环从次数,/是取商,所以数组长度单双都可以使用
        for (int i = 0; i <= num.length / 2; i++) {
            int temp = num[i];
            num[i] = num[num.length - 1 - i];
            num[num.length - 1 - i] = temp;
        }
        //将降序好的数组遍历输出
        for (int i = 0; i < num.length; i++) {
            System.out.println(num[i]);
        }
    }

对数组部分排序,也就是对数组a的下标从fromIndex到toIndex-1的元素排序,注意:下标为toIndex的元素不参与排序

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

Comparator排序

public static void sort(T[] a,int fromIndex,int toIndex, Comparator c)
public static void main(String[] args) {
     //注意,要想改变默认的排列顺序,不能使⽤基本类型(int,double, char)
     //⽽要使⽤它们对应的类
     Integer[] a = {9, 8, 7, 2, 3, 4, 1, 0, 6, 5};
     //定义⼀个⾃定义类MyComparator的对象
     Comparator cmp = new MyComparator();
     Arrays.sort(a, cmp);
     for(int i = 0; i < a.length; i ++) {
         System.out.print(a[i] + " ");
     }
 }

 //Comparator是⼀个接⼝,所以这⾥我们⾃⼰定义的类MyComparator要implents该接⼝
 //⽽不是extends Comparator
class MyComparator implements Comparator<Integer>{
     @Override
     public int compare(Integer o1, Integer o2) {
     //如果n1⼩于n2,我们就返回正值,如果n1⼤于n2我们就返回负值,
     //这样颠倒⼀下,就可以实现反向排序了
     if(o1 < o2) {
         return 1;
     }else if(o1 > o2) {
         return -1;
     }else {
         return 0;
     }
 }

字符排序

    private static void CharSortDemo() {
        char[] nums = {'A', 'V', 'R', 'a', 'p', 'o'};
        Arrays.sort(nums);
        System.out.println(Arrays.toString(nums));
    }

去重

    /**
     * 去重
     */
    private static void RepeatDemo() {
        //去除:将重复的改成0(默认值)
        int[] nums = {50, 32, 52, 39, 38, 51, 31, 10, 51, 13, 25, 5};
        int[] newNums = new int[nums.length];
        for (int i = 0; i < nums.length; i++) {
            int ele = nums[i];
            boolean has = false;
            for (int j = 0; j < newNums.length; j++) {
                if (ele == newNums[j]) {
                    has = true;
                }
            }
            if (!has) {
                newNums[i] = ele;
            }
        }
        System.out.println(Arrays.toString(newNums));

        //将默认值设置从空
        int size = 0;
        int[] indexArray = new int[newNums.length];
        for (int i = 0; i < newNums.length; i++) {
            if (newNums[i] != 0) {
                indexArray[size] = i;
                size++;
            }
        }
        System.out.println(Arrays.toString(indexArray));
        int[] finalResult = new int[size];
        for (int i = 0; i < finalResult.length; i++) {
            int index = indexArray[i];
            finalResult[i] = newNums[index];
        }
        System.out.println(Arrays.toString(finalResult));
    }

二叉查找

使⽤折半的形式, ⼀次性剔除⼀半的⽆效元素, 提⾼了查找的效率

使⽤⼆分查找的数组必须是有序

	private static void BinSearchDemo() {
        int[] nums = new int[]{5, 10, 13, 25, 31, 32, 38, 39, 45, 50, 51, 52};
        int n = 50;
        int startIndex = 0;
        int endIndex = nums.length - 1;
        if (n < nums[startIndex] || n > nums[endIndex]) {
            System.out.println(n + "不在当前数组");
            return;
        }
        while (startIndex <= endIndex) {
            int middleIndex = (startIndex + endIndex) / 2;
            if (n == nums[middleIndex]) {
                System.out.println(n + "在数组nums中");
                return;
            } else if (n > nums[middleIndex]) {
                startIndex = middleIndex + 1;
            } else {
                endIndex = middleIndex - 1;
            }
        }
        System.out.println(n + "不在当前数组");
    }

常见问题

  1. ArrayIndexOutOfBoundsException

    数组下标越界异常

    访问不存在的下标

  2. NullPointerException

    空指针异常

    栈中的数组变量没有指向堆内存中的数组实体

public static void main(String[] args) {
    int[] arr = new int[2];
    //会出现数组⻆标越界异常
    
    int i = arr[2];
    arr = null;
    //会出现空指针异常
    i = arr[0];
}

扩容

  1. 创建数组的时候,必须指定长度,并且创建之后没有自发改变长度

  2. 扩容的思路

    • 创建大于原数组长度的新数组

    • 将原数组中的元素一次复制到新数组中

  3. 实现的方式

    • 循环将原数组中的所以元素依次复制
    • System.arraycopy(原数组,原数组起始,新数组,新数组起始,⻓度)
    • java.util.Arrays.copyOf(原数组,新⻓度) —— 返回⼀个带有原值的新数组

  4. 实现

	private static void CapacityExpansionDemo() {
        int[] nums = {1, 67, 45, 34, 29, 645, 3};
        int[] newNums = new int[nums.length + 5];
        
        //方案一
        for (int i = 0; i <nums.length ; i++) {
            newNums[i]=nums[i];
        }
        nums=newNums;
        System.out.println(Arrays.toString(nums));*/

        //方案二
        /*
        src 源数组 
        srcPos 在源数组中的起始位置 
        dest 目标数组 
        destPos 在目标数据中的起始位置 
        length 要复制的数组元素的数量
        */    
        System.arraycopy(nums, 0, newNums, 0, nums.length);
        nums=newNums;
        System.out.println(Arrays.toString(nums));

        //方案三
         /*
        original 要复制的数组
     	newLength 要返回的副本长度
        */  
        int[] newNums1 = Arrays.copyOf(nums, nums.length + 5);
        nums = newNums1;
        System.out.println(Arrays.toString(nums));
    }

应用

平均值

需求:给定一个整数数组,统计数组中所有元素的平均值。

    public static void main(String[] args) {
       int[] num={11,55,19,56,14};
       int sum=0;
       for (int i=0;i<num.length;i++){
           sum=sum+num[i];
       }
        System.out.println(sum/num.length);
    }

判定是否存在

需求:给定一个整数数组,读入一个整数n,如果n在数组中存在,输出下标,不存在则输出-1。

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n=scanner.nextInt();
        int[] num = {11, 55, 19, 56, 14};
        for (int i = 0; i < num.length; i++) {
            if (num[i] == n) {
                System.out.println(i);
                return;
            }
        }
        System.out.println("-1");
    }

多维数组

Java中所谓的多维数组是通过数组的数组来实现的,也就是说数组中的每⼀个元素是⼀个数组
既然数组中的每⼀个元素是⼀个数组,那么就不可能去硬性规定数组中的元素数组的⻓度要完全⼀致,这也就出现
了 所谓的锯⻮数组

声明、创建和初始化

  1. 声明

    • 数组类型[] 数组名[] 数据类型 数组名[][]
    • 数据类型[][] 数组名
  2. 创建

    • 数组名=new 数据类型 [行数] [列数]

    注意:在创建数组的时候,必须声明行数,可以不声明列数

    行数救赎外层数组的长度,列数是内层数组的长度,如果不声明列数,等于单纯的声明数组

    public static void main(String[] args) {
        //一维数组
        int[] nums = new int[5];
        
        //多维数组的声明
        int[][] numss;
        int[] nums1[];
        int nums2[][];
        
        //多维数组的初始化
        //1、确定长度的动态初始化
        // 只要一个数组num1,内部数组未定长,所以无数组
        int[][] num1 = new int[6][];
        //一个7个,外部1内部6个,内部每一个长度5
        int[][] multNums = new int[6][5];
        //2、确定元素的静态初始化
        int[][] num2 = {
                {1, 2, 3},
                {5, 6, 2},
                {8, 4},
                {9, 26, 5, 4, 2},
                {9}
        };
        System.out.println("num2数组元素:");
        for (int i = 0; i < num2.length; i++) {
            System.out.println(Arrays.toString(num2[i]));
        }

        //3、确定元素的静态初始化 -new
        int[][] num3 = new int[][]{
                {1, 2, 3},
                {5, 6, 2},
                {8, 4},
                {9, 26, 5, 4, 2},
                {9}
        };
        System.out.println("num3数组元素:");
        for (int i = 0; i < num3.length; i++) {
            System.out.println(Arrays.toString(num3[i]));
        }

        //遍历添加元素
        int[][] multArray1 = new int[6][5];
        for (int i = 0; i < multArray1.length; i++) {
            for (int j = 0; j < multArray1[i].length; j++) {
                multArray1[i][j] = j;
            }
        }
        //单独添加
        multArray1[1][2]=999;
		
        //遍历内部数组
        System.out.println("multNums数组元素:");
        for (int i = 0; i < multArray1.length; i++) {
            System.out.println(Arrays.toString(multArray1[i]));
        }
        
        //遍历内部数组元素
        System.out.println("multNums数组元素:");
        for (int i = 0; i < multArray1.length; i++) {
            for (int j = 0; j < multArray1[i].length; j++) {
                System.out.print(multArray1[i][j] + "\t");
            }
        }
    }

内存模型

总结

1. 数组
    存放多个值得容器
    必须确定数据类型
    必须确定⻓度
    ⻓度和数据类型都不能修改
2. 数组的创建
    静态初始化 : 先确定具体的数值, 由虚拟机来确定类型和⻓度
    动态初始化 : 先确定类型和⻓度, ⾥⾯是默认值
3. 数组的默认值
    整数: 0
    ⼩数: 0.0
    字符: \u0000
    布尔: false
    引⽤数据类型: null
4. 数组的使⽤
    通过⻆标操作数组, ⻆标从 0开始, 到数组的⻓度 -1 结束
    获取元素 : arr[⻆标]
    设置元素 : arr[⻆标] =;
5. 数组和循环的结合
    循环中的变量 i 设置为从0开始 到 arr.length-1结束
    for(int i = 0 ; i < arr.length ; i++){}
tem.out.print(multArray1[i][j] + "\t");
            }
        }
    }

内存模型

总结

1. 数组
    存放多个值得容器
    必须确定数据类型
    必须确定⻓度
    ⻓度和数据类型都不能修改
2. 数组的创建
    静态初始化 : 先确定具体的数值, 由虚拟机来确定类型和⻓度
    动态初始化 : 先确定类型和⻓度, ⾥⾯是默认值
3. 数组的默认值
    整数: 0
    ⼩数: 0.0
    字符: \u0000
    布尔: false
    引⽤数据类型: null
4. 数组的使⽤
    通过⻆标操作数组, ⻆标从 0开始, 到数组的⻓度 -1 结束
    获取元素 : arr[⻆标]
    设置元素 : arr[⻆标] =;
5. 数组和循环的结合
    循环中的变量 i 设置为从0开始 到 arr.length-1结束
    for(int i = 0 ; i < arr.length ; i++){}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值