• Java数组


    0.前言

    数组是一个固定长度的,包含了相同类型数据的容器

    1.声明数组

    数据类型[ ] 数组名;   // 声明一个数组

    例如:

    int[] array1; // 声明数组array1
    
    • 1

    2.数组的初始化(创建数组)

    初始化,就是在内存中为数组开辟空间,并将数据存入容器的过程

    (1)静态初始化

    完整格式:

    数据类型[ ] 数组名 = new 数组名[ ]{ value1,value2,……};
    eg. int[ ] arr = new arr[ ] {1,2,3};

    日常使用中,更倾向于简化格式

    数据类型[ ] 数组名 = { value1,value2,……};
    eg. int[ ] arr = {1,2,3};

    更多例子:

    double[] arr1 = {1.2,2.3,4.5 };
    String arr2  = {"hello","world"};
    
    • 1
    • 2

    (2)动态初始化

    初始化时只指定数组长度,由系统为数组分配初始值。

    数据类型[ ] 数组名 = new 数据类型[ 数组长度 ]
    eg. int[ ] array = new int[10];

    例如:

    public class HelloWorld {
        public static void main(String[] args) {
           double[] array = new double[10] // 创建一个长度为10的数组
           array[0] = 3.4; 
           array[1] = 5.8; 
           System.out.println(array[0]);  // 3.4
           System.out.println(array[1]);  // 5.8
           // 没有手动赋值,系统自动为其赋值(默认)
           System.out.println(array[2]);  // 0.0
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    (3)静态和动态初始化的区别

    在这里插入图片描述

    3.数组的操作

    用for循环基本可以搞定大部分操作;

    增强for循环(for-each):

    for(type element: array)
    {
    System.out.println(element);
    }

    (1)读取元素

    说到读取元素,不得不提数组在计算机中的内存。

    对于数组而言,计算机会在内存中为其申请一段连续的空间,并且会记下索引为 0 处的内存地址。以数组 [“C”, “O”, “D”, “E”, “R”] 为例,它的各元素对应的索引及内存地址如下图所示:

    在这里插入图片描述

    一旦知道了内存地址就可以立即访问到该元素,因此它的时间复杂度是常数级别O(1)

    总之:

    • 数组下标都是从0开始的
    • 数组内存空间的地址是连续的

    (2)查找元素

    这里就是我们经常说的暴力搜索,从头开始搜索;当然最典型的改进就是二分查找

    (3)插入元素

    正是因为数组的在内存空间的地址是连续的,所以在插入元素的时候,就很大可能要 移动 其他元素的地址。

    如果是在数组的结尾插入元素,那比较方便。即计算机通过数组的长度和位置计算出即将插入元素的内存地址,然后将该元素插入到指定位置即可。

    但如果是想在将该元素插入到数组中的其他位置,这时首先需要为该元素所要插入的位置腾出空间,然后进行插入操作。

    (4)删除元素

    删除元素与插入元素的操作类似

    当删除掉数组中的某个元素后,数组中会留下 空缺 的位置,而数组中的元素在内存中是连续的,这就使得后面的元素需对该位置进行 填补 操作;

    数组的元素是不能删的,只能覆盖。

    4.数组作为函数参数

    只要记住:

    方法在传递基本数据类型时,传递的是真实的数据,形参的改变,不影响实参的值

    方法在传递引用数据类型时,传递的是地址值,形参的改变,影响实参的值

    所以数组作为引用类型,在作为形参时,要注意它是否被改变

    public static void printArray(int[] array) {
      for (int i = 0; i < array.length; i++) {
        System.out.print(array[i] + " ");
      }
    }
    
    printArray(new int[]{3, 1, 2, 6, 4, 2})
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    总之:

    当两个数组指向同一个空间时,其中一个数组对小空间中的值发生了改变,那么其他数组再次访问的时候都是修改后的结果了

    5.二维数组

    (1)内存分析

    二维数组的本质上仍然是一个一维数组,只是将数组中的每个元素变成了一维数组。

    内部的一维数组仍然从索引 0 开始。

    在这里插入图片描述

    与一维数组一样,二维数组同样会在内存中申请一段 连续 的空间,并记录第一行数组的索引位置,即 A[0][0] 的内存地址,如图:

    在这里插入图片描述

    (2)声明&初始化

    定义:

    int[][] a=new int[5][5];
    String[][] b=new String[3][4];
    
    • 1
    • 2

    初始化:

    //静态初始化
    int[][] a={{1,2,3},{4,5,6,7},{8,9,10,11}};
    
    //动态初始化
    String[][] b=new String[10][10];
    b[0]=new String[]{"zahngsan","lisi","wangwu"};
    b[1]=new String[]{"java","python","c++"};
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    (3)遍历

    public static void main(String[] args) {
            //静态初始化
            int[][] a={{1,2,3,4},{4,5,6,7},{8,9,10,11}};
            //调用print方法
            print(a);
        }
        public static void print(int[][] a){
            //遍历
            // a.length为 3,a[0].length为 4
            for (int i = 0; i < a.length; i++) {
                for (int j = 0; j < a[i].length; j++) {
                    System.out.print(a[i][j]+" ");
                }
                System.out.println();
            }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    6.Arrays类

    java.util.Arrays 类能方便地操作数组

    直接看方法:

    方法含义
    String toString(数组)把数组拼接成一个字符串
    int [ ] copyOf(原数组,新数组长度)拷贝数组
    int [ ] copyOfRange(原数组,起始索引,结束索引)拷贝数组(指定范围),左闭右开
    void fill(int[ ] a, int val)填充数组,将指定的 val 值分配给数组a指定范围中的每个元素
    boolean equals(long[ ] a, long[ ] a2)如果两个数组以相同顺序包含相同的元素,则两个数组是相等的
    void sort(Object[ ] a)对指定对象数组根据其元素的自然顺序进行升序排列
    void sort​(类型[] a, Comparator c)使用比较器对象自定义排序
    int binarySearch(Object[ ] a, Object key)用二分查找算法在给定数组中搜索给定值的对象(Byt(在调用前必须排序好)

    看几个示例熟悉用法

    e.g.1

      int[] a={1,5,7,2,4,9};
          
      // 将数组转化为字符串输出
      String str=Arrays.toString(a);      
      System.out.println("字符串:"+str);
      
     // 拷贝操作,新数组长度是5,从原数组第一个元素开始
     int[] dp = Arrays.copyOf(a,5);
     System.out.println("拷贝后数组是:"+Arrays.toString(dp)); // 拷贝后数组是:[1, 5, 7, 2, 4]
    
     // 拷贝操作,拷贝原数组下标从1-5(不含)
      int[] db = Arrays.copyOfRange(a,1,5);
      System.out.println("拷贝后数组是:"+Arrays.toString(db)); // 拷贝后数组是:[5, 7, 2, 4]
    
      //所有元素都赋值成特定值
      Arrays.fill(a,10);                  
      System.out.println("赋值后:"+Arrays.toString(a));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    输出:

    字符串:[1, 5, 7, 2, 4, 9]
    拷贝后数组是:[1, 5, 7, 2, 4]
    拷贝后数组是:[5, 7, 2, 4]
    赋值后:[10, 10, 10, 10, 10, 10]

    eg2 排序

    再说一下排序,分为自然排序和自定义排序

    自定义排序 void sort​(类型[] a, Comparator c)

    设置 Comparator接口 对应的比较器对象,来定制比较规则

    • 如果认为左边数据 大于 右边数据 返回正整数
    • 如果认为左边数据 小于 右边数据 返回负整数
    • 如果认为左边数据 等于 右边数据 返回0
      // 1、默认升序排序
       int[] ages = {34,12,42,23};
       Arrays.sort(ages);
       System.out.println(Arrays.toString(ages));
    
       // 2、自定义比较器对象,只能支持引用类型的排序!
       Integer[] ages1 = {34,12,42,23};
    
      /*
      参数一:被排序的数组必须是引用类型的元素
      参数二:匿名内部类对象,代表了一个比较器对象。
      */
      Arrays.sort(ages1,new Comparator<Integer>( ) {
                    @Override
                    public int compare(Integer o1,Integer o2) {
                          // 降序排列
                            return o2-o1;
                          // 升序排序即 return o1-o2;
                            }
                            });
      System.out.println(Arrays.toString(ages1));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    输出:

    [12, 23, 34, 42]
    [42, 34, 23, 12]

    当然,自定义排序还可以对 对象 进行排序,比如按照对象的某一属性

    如可以自己定义一个学生类,按照学生的身高排序

    	Student[] students = new student[3];
    	students[0] = new Student( name: "张三" ,age: 23 , height: 172);
    	students[1] = new student( name: "李四",age: 19 , height: 187);
    	students[2] = new student( name: "王五",age: 22 ,height:178);
    	system.out.println(Arrays.toString(students));
    	
        // Arrays.sort(students); 直接排序会报错
        
        Arrays.sort(students, new Comparator<Student>() {
                 @0verride
            public int compare(Student o1,Student o2){
                 //自己指定比较规则
                return o1.getAge() - o2.getAge(; //按照年龄升序排序!}
            });
                System.out.println(Arrays.toString(students));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    参考链接:
    https://leetcode.cn/leetbook/read/array-and-string/yjcir/
    https://www.runoob.com/java/java-array.html

  • 相关阅读:
    kinetic: 编译navgation包遇到的问题
    【Vue3】Vue3 vs Vue2
    unipush2.0实现APP消息推送(2)云函数多个方法的创建与使用
    分布式存储系统之Ceph集群CephFS基础使用
    【前端笔记】小记一次Antd Vue 1.x (for vue2.x) icons组件按需引入的实现
    IDEA--tomcat日志乱码
    B2B2C系统亮点是什么?如何助力珠宝首饰企业打造全渠道多商户商城管理体系
    Shiro - Shiro简介;Shiro与Spring Security区别;Spring Boot集成Shiro
    Vue+element 权限管理业务实现
    惹恼开源社区!微软道歉:恢复 .NET SDK 热重载功能
  • 原文地址:https://blog.csdn.net/ji_meng/article/details/126143070