• java中的数组


    关于数组的基础知识
    一维数组
    二维数组

    关于数组的基础知识

    1、 Java语言中的数组是一种引用数据类型,不属于基本数据类型。数组的父类是Object。
    2、数组实际上是一个容器,可以同时容纳多个元素。(数组是一个数据的集合)数组:宇面意思是“一组数据”。
    3、数组当中可以存储"基本数据类型"的数据,也可以存储"引用数据类型"的数据。
    4、数组因为是引用类型,所以数组对象是堆内存当中。(数组是存储在堆当中的)
    5、数组在内存方面是怎么样的一个图形?
    在这里插入图片描述
    6、数组当中如果存储的是"java对象”的话,实际上存储的是对象的“引用(内存地址)"。
    7、数组一旦创建,在java中规定,数组长度不可变。
    8、数组的分类:一维数组、二维数组、三维数组、多维救组... (一维数组较多,二维数组偶尔使用)
    所有的数组对象都有Length属性(java自带的),用来获取数组中元素的个数。
    9、java中的数组要求数组中元素的类型统一。
    比如int类型数组只能存储int类型,Person类型数组只能存储person类型。
    10、数组在内存方面存储的时候,数组中的元素内存地址(存储的每一个元素都是有规剧的挨着排列的)是连续的。内存地址连续这是救组存储元素的特点(符色)。数组实际上是一种简单的教据结构。
    11、所有的数组都是拿"第一个小方框的内存地址”作为整个数组对象的内存地址。数组中每一个元素都是有下标的,下标从0开始,以1递增。最后一个元素的下标是:Length - 1。下标非常重要,因为我们对数组中元素进行"存取"的时候,都需要通过下标来进行。
    例图:
    在这里插入图片描述

    • 数组这种数据结构的优点和缺点
      1、优点:
      查询/查找/检索某个下标上的元素时效事极高。可以说是查询效率最高的一个数据结构。
      为什么检索效率高?
      ①:每一个元素的内存地址在空间存储上是连续的。
      ②:每一个元素类型相同,所以占用空间大小一样。
      ③:知道第一个元素内存地址,知道每一个元素占用空间的大小,又知道下标,所以通过一个数学表达式就可以计算出某个下标上元素的内存地址。直接通过内存地址定位元素,所以数组的检索效率是最高的。数组中存储100个元素,或者存储100万个元素,在元素查询/检索方面,效率是相同的。因为数组中元素查找的时候不会一个一个找,是通过数学表达式计算出来的。(算出一个内存地址,直接定位的。)
      2、缺点
      ①:由于为了保证数组中每个元素的内存地址连续,所以在数组上随机删除或者增加元素的时候效率较低,因为随机增删元素会涉及到后面元素统一向前或者向后位移的操作。
      ②:数组不能存储大数据量。
      因为很难在内存空间上找到一块特别大的连续的内存空间。注意:对于数组中最后一个元素的增删,是没有效率影响的。

    一维数组

    • 怎么声明/定义一个一维数组?
      语法格式:
    int [] arrayl;
    double[] array2;
    boolean[] array3;
    String[] array4;
    Object[] array5;
    
    • 怎么初始化一个一维数组呢?
      包括两种方式:静态初始化一维数组,动态初始化一堆数组。静态初始化语法格式:
    int[] array = {100, 2100, 300, 55};
    

    动态切始化语法格式:

    int[] array = new int[5];
    /*这里的5表示数组的元素个数。初始化
    一个5个长度的int类型数组,每个元素默认值0.
    */
    
    String[] names = new String[6];
    /*初化6个长度的string类型数组,
    每个元素默认值null。*/
    
    • 一维数组中元素的访问
      代码示例(静态初始化方式):
    public class DemoTest{
        public static void main(String[] args) {
            //静态初始化方式
            int[] a = {1, 2, 3, 4, 5, 6};
            //所有的数组对象都有length属性
            System.out.println("数组中的元素个数为:" + a.length);
            //数组中每一个元素都有下标
            // 通过下标对数组中的元素进行存和取。
            // 取(读)
            System.out.println("第一个元素是:" + a[0]);
            System.out.println("最后一个元素是:" + a[5]);
            System.out.println("最后一个元素是:" + a[a.length - 1]);
            //存(改)
            //把第一个元素改为111
            a[0] = 111;
            System.out.println("修改后的第一个元素是:" + a[0]);
            //把最后一个元素改为666
            a[a.length - 1] = 666;
            System.out.println("修改后的最后一个元素是:" + a[a.length - 1]);
        }
    }
    

    输出:
    在这里插入图片描述

    • 一维数组遍历
      代码示例:
    public class DemoTest{
        public static void main(String[] args) {
            int[] a = {1, 2, 3, 4, 5, 6};
    
            for (int i = 0; i < a.length; i++) {
                System.out.println(a[i]);
            }
    
            for (int i = a.length; i > 0; i--) {
                System.out.println("颠倒顺序输出:" + a[i - 1]);
            }
            
            //System.out.println(a[6]);
            /*出现著名异常:
            ArrayIndexOutOfBoundsException
            也就是:下标越界异常
            常见著名异常还有:
            空指针异常、类型转换异常.
            */
        }
    }
    
    • 动态初始化一维数组
      代码示例:
    public class DemoTest{
        public static void main(String[] args) {
            /*采用动态初始化的方式创建长度为4的int数组,
            数组中每个元素的默认值是0*/
            int[] a = new int[4];
            for (int i = 0; i < a.length; i++) {
                System.out.println("数组中下标为" + i + "的元素是:" + a[i]);
            }
            /*采用动态初始化的方式创建长度为3的Object数组,
            数组中每个元素的默认值是null*/
            Object[] ob = new Object[3];
            for (int i = 0; i < ob.length; i++) {
                System.out.println(ob[i]);
            }
            /*采用静态初始化的方式创建*/
            Object object = new Object();
            Object object1 = new Object();
            Object object2 = new Object();
            Object[] o = {object,object1,object2};
            /*还可以采用以下方式:
            * Object[] o = {new Object(), new Object(), new Object()};
            * */
            for (int i = 0; i < o.length; i++) {
                System.out.println(o[i]);
            }
    
        }
    }
    
    • 什么时候采用静态初始化方式?什么时候使用动态初始化方式呢?

    当创建数组的时候,确定数组中存储那些具体的元素时,采用静态初始化方式。

    当创建数组的时候,不确定将来教组中存储那些数据,你可以采用动态初始化的方式,预先分配内存空间。

    • 当方法的参数是数组时
      1、代码示例:
    public class DemoTest{
        public static void main(String[] args) {
            int[] x = {1,2,3};
            String[] s = {"qqq","www","eee"};
            printArray(x);
            printArray(s);
        }
        /*
        这里使用静态方法比较方便,
        不需要new对象
        */
        public static void printArray(int[] array){
            for (int i = 0; i < array.length; i++) {
                System.out.println(array[i]);
            }
        }
        public static void printArray(String[] args){
            for (int i = 0; i < args.length; i++) {
                System.out.println(args[i]);
            }
        }
    }
    

    输出:
    在这里插入图片描述
    2、 直接传递一个静态数组

    printArray(new int[]{7,8,9});
    
    • main方法上面的"string[] args"有什么用?
      1、JVM负责调用main方法
      JVM调用main方法的时候,会自动传一个String数组过来。
      2、代码示例:
    public class DemoTest{
        public static void main(String[] args) {
            System.out.println(args.length);//输出:0
            /*
            * 经过测试,args不是null,而是默认为0.
            * 这个数组什么时候里面会有值呢?
            * 其实这个数组是留给用户的,
            * 用户可以在控制台上输入参数,
            * 这个参数自动会被转换为"string[] args"。
            * */
            for (int i = 0; i < args.length; i++) {
                System.out.println(args[i]);
            }
            /*
             * 用命令行这样运行程序: java DemoTest abc def
             * 那么这个时候JVM会自动将"abc def"通过空格
             * 的方式进行分离,分离完成之后,自动放到
             * "String[] args"数组里面
             * 在工具里面需要如下设置
             * */
        }
    }
    

    设置前输出:
    在这里插入图片描述
    在IDEA里面设置后:
    在这里插入图片描述
    输出:
    在这里插入图片描述

    • 数组中存储引用数据类型
      1、一维数组的深入,数组中存储的类型为:引用数据类型
      对于数组来说,实际上只能存储java对象的“内存地址”。数组中存储的每个元素是“引用"。
      2、代码示例:
    public class DemoTest{
        public static void main(String[] args) {
            Demo a1 = new Demo();
            Demo a2 = new Demo();
            Demo[] demos1 = {a1,a2};
            for (int i = 0; i < demos1.length; i++) {
                Demo a = demos1[i];
                a.move();
                //也可以采用以下方法,更简洁。
                demos1[i].move();
            }
    
            Demo[] demos = {new Cat(), new Bird()};
            for (int i = 0; i < demos.length; i++) {
                //demos[i].move();
    
                if(demos[i] instanceof Cat){
                    Cat cat = (Cat)demos[i];
                    cat.catchM();
                }else if(demos[i] instanceof Bird){
                    Bird bird = (Bird)demos[i];
                    bird.fly();
                }
                /*这里需要判断类型,然后向下强制转换
                * 到相应的类型,才能调用其特有的方法*/
            }
    
        }
    }
    
    public class Demo{
        public void move(){
            System.out.println("animal move");
        }
    }
    
    public class Cat extends Demo{
        @Override
        public void move() {
            System.out.println("猫");
        }
        public void catchM(){
            System.out.println("猫在抓老鼠");
        }
    }
    
    public class Bird extends Demo{
        @Override
        public void move() {
            System.out.println("鸟儿");
        }
        public void fly(){
            System.out.println("flying");
        }
    }
    
    • 一维数组的扩容/拷贝
      1、在java开发中,数组长度一旦确定不可变,那么数组满了怎么办?
      数组满了,需要扩容。
      java中对数组的扩容是:先新建一个大容量的数组,然后将小容量数组中的数据一个一个拷贝到大数组当中。
      2、结论:数组扩容效率较低。
      因为涉及到烤贝的问题。所以在以后的开发中请注意:尽可能少的进行数组的拷贝。
      可以在创建数组对象的时候预估计以下多长合适,最好预估准确,这样可以减少数组的扩容次数。提高效率。
      3、代码示例:
    public class DemoTest{
        public static void main(String[] args) {
            /*System.arraycopy(5个参数);
            5个参数分别为:
            (拷贝源数组名,
            需要拷贝的起始位置(下标),
            目标数组名,
            需要拷贝到目标数组的起始位置(下标),
            拷贝长度)
            拷贝长度可以理解为:
            将源数组上的一段剪下来,
            覆盖在目标数组的一段相应位置。
            */
            //拷贝源
            int[] src = {1,2,3,4};
            //拷贝到目标数组上
            int[] dest = new int[7];
            //调用arraycopy方法完成数组的拷贝
            System.arraycopy(src, 1, dest, 3, 2);
            //拷贝之后遍历目标数组
            for (int i = 0; i < dest.length; i++) {
                System.out.println(dest[i]);
            }
        }
    }
    

    输出:
    在这里插入图片描述

    public class Demo{
        //数组中如果存储的元素是引用也可以拷贝。
        public static void main(String[] args) {
            Object[] object = {new Object(), new Object(), new Object()};
            Object[] newobj = new Object[5];
            System.arraycopy(object,0,newobj,0,object.length);
            for (int i = 0; i < newobj.length; i++) {
                System.out.println(newobj[i]);
            }
        }
    }
    

    输出:
    在这里插入图片描述
    4、相应的内存图:
    在这里插入图片描述

    二维数组

    • 关于二维数组的描述
      1、二维数组其实是一个特殊的一维数组,特殊在这个一维数组当中的每一个元素是一个一维数组。
      2、二维数组的访问:
    a[二维数组中的一维教组的下标][一维数组的下标]
    
    • 二维数组静态初始化:
    int[][] a = {
                    {1,2,3},
                    {4,5,6},
                    {7,8,9}
            };
    
    • 二维数组的length属性及遍历
      代码示例:
    public class DemoTest{
        public static void main(String[] args) {
            int[][] a = {
                    {1,2,3},
                    {4,5,6},
                    {7,8,9}
            };
            /*length属性*/
            System.out.println(a.length);
            System.out.println("一:" + a[0].length
             + " 二:" + a[1].length + " 三:" + a[2].length);
            System.out.println("=====================");
            /*遍历*/
            for (int i = 0; i < a.length; i++) {
                for (int j = 0; j < a[i].length; j++) {
                    System.out.println(a[i][j]);
                }
            }
    
        }
    }
    
    • 二维数组的动态初始化
    public class Demo{
        public static void main(String[] args) {
            int[][] a = new int[3][4];
            a[0] = new int[]{1, 1, 1, 1};
            a[1] = new int[]{2, 2, 2, 2};
            a[2] = new int[]{3, 3, 3, 3};
            printArray(a);
        }
    
        public static void printArray(int[][] array){
            for (int i = 0; i < array.length; i++) {
                for (int j = 0; j < array[i].length; j++) {
                    System.out.print(array[i][j]);
                }
                System.out.println();
            }
        }
    }
    
  • 相关阅读:
    Java知识系统回顾整理01基础05控制流程02 switch
    Java知识系统回顾整理01基础05控制流程01if
    Java知识系统回顾整理01基础04操作符07Scanner
    Java知识系统回顾整理01基础04操作符06三元运算符
    Java知识系统回顾整理01基础04操作符05赋值操作符
    Java知识系统回顾整理01基础04操作符04位操作符
    Java知识系统回顾整理01基础04操作符03逻辑运算符
    leetcode-----74. 搜索二维矩阵
    leetcode-----73. 矩阵置零
    leetcode-----72. 编辑距离
  • 原文地址:https://www.cnblogs.com/yu011/p/12632747.html
Copyright © 2020-2023  润新知