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();
        }
    }
}
原文地址:https://www.cnblogs.com/yu011/p/12632747.html