来吧!给你不一样的数组深入讲解

我的未来我决定 提交于 2019-12-22 03:46:17

不知道为啥,数组让我写的很痛苦!写到深夜两点啊,不容易,各位看官,记得点赞😂,不然没动力了

数组小谈😁

庆哥: 嗨,小白,知道啥是数组吗?😎小白: 你看你这话说的,数组那还不简单,学计算机的没有不知道数组的吧,我们刚开始接触C语言的时候就有数组啊,现在在学习java,也有数组啊,一般不就这样嘛😁

int[] array = new int[10]

这就创建了一个长度为10的数组,是不是?😀

庆哥: 嗯嗯,你还知道数组的啥啊。比如特性啥的?

小白: 这个嘛,数组啊,最经典的不就是可以根据数组下标来读取数据吗?比如上面定义的那个长度为10的数组,可以使用array[1]来获得数组第二个位置的数据。

庆哥: 为啥不是第一个的数据,那不是1吗?

小白: 这个嘛,那是因为数组下标是从0开始的,所以实际上1就是2的位置,就像这样:

来吧!给你不一样的数组深入讲解!庆哥: 那数组下标为啥从0开始啊😎

小白: 嗯。。。这个?😂不知道

庆哥: 在Java中数组其实可以看做是一个对象嘛?😉

小白: 纳尼?没有考虑过这个问题啊🤣

庆哥: 知道Array和Arrays嘛🤗

小白: 不是太清楚😅

庆哥: 哈哈,来吧,今天就让你彻底搞懂数组这家伙😎

小白: 小板凳已备好😄

啥是数组啊😂

天马星空看数组😎

庆哥: 既然我们要学习数组,那首要的任务就是先要弄懂,啥是数组?你现在清空大脑,不要想着什么数组是数据结构,什么连续内存,什么随机访问,什么不可变的,抛出你之前关于数组的所有认知,从零开始,你想想,数组是个啥?😁

小白: 那我要发挥我超强的想象力了哦😂,数组嘛,单从这俩字啊,我想着这玩意应该是个跟棍似的😂,一组一组的嘛,长长的🤣,然后是数据嘛,人家是数组,那应该就是跟数据有关的,组?我们平常会说一组一组的,比如几人一组,那这个数组就是一些数据在一块。。。。我在说啥😅

庆哥: 可以啊,你这想象力😂,那我来说下我的理解吧,初看数组这货,我就觉得啊,它在java中应该也是个类,然后我们也可以通过最基本的new来创建一个数组,刚开始就这样感觉得,但是谁知道这家伙完全不按照套路出牌啊😂

小白: 你这样一说也真是的,我本来也以为数组可以使用new嘞,有的时候还是有点疑惑的,特别是遇到Array这个类就更迷惑了😂

庆哥: 的确,我刚开始也是这样,觉得这个Array不就是数组嘛,然后我还这样试过😂

来吧!给你不一样的数组深入讲解!哈哈,我当时还迷惑,这是咋回事啊,这不是创建数组嘛🤣

小白: 这是咋回事啊,为啥会报错啊😅

庆哥: 这个嘛,我们看看Array的源码就知道了来吧!给你不一样的数组深入讲解!看到了吧,它的构造方法是私有的,所以是不能被实例化的,因为我们使用new就是通过构造方法去创建啊,而这里是私有的,所以是不行滴,知道了吧😀

小白: 嗯嗯,看来我对这个数组还真的是不了解啊😂,庆哥这次要好好和我说说😄

java中的数组

庆哥: 没问题😎,那我们言归正传,看看java中的数组到底是个啥,在java中啊,我们可以这样理解数组:

数组这家伙就是一个数据集合,而且它还是有序的,就是很多数据搁在一块,一个挨着一个,而且每个数据的类型都是相同的

这里简单大白话说了啥是数组,有必要还是画个图,来加深下印象,对了对了,之前画了个图,就用这个

来吧!给你不一样的数组深入讲解!好了,现在对于数组,给你文字说了是啥,现在再看个图,这里就相当于有一个数组,这个数组有10个数据,你看他们是不是一个挨着一个,然后每个数据还有一个下标,这个下标就相当于给每个数据进行编号,你想啊,编号有啥好处?

是不是更加容易寻找了,对号入座嘛!所以这里就引出了数组的一个大大的特点:

人家支持随机访问啊

小白:  这个是不是就是可以使用下标访问数据的特性😀

庆哥: 嗯嗯,是的,我们接着来说,我们现在对数组有个大致印象, ,要知道数组最终是用来干嘛的。人家是用来存放数据的,我们还是先来看看数组的的相关代码吧:

int[] a = new int[10];

看,这就创建了一个数组,不是我们想的使用new的方式,其实从代码我们就能猜到,这个数组的长度是10,啥意思,数组人家是有长度的。

小白: 这个是必须要给它指定一个长度吧

数组的声明

庆哥: 这个就牵涉到数组的声明了,数组是用来存放数据的,那我们要用它的话就要先创造它吧,之前说了,人家不是使用new,人家是这样的形式

int[] a = new int[10];

那么这样可以吗?

int[] a = new int[];

有啥区别?是不是少了个10,行吗这样,我们看看

来吧!给你不一样的数组深入讲解!看到了,不行,为啥不行啊,你想想?

小白: 这个嘛,这里的10是在给数组一个指定的长度吧,难道不能默认长度为0吗?

庆哥: 这里就要看数组的一些特点了,对于数组啊,人家是有序数据的集合,在内存中来展示就是人家需要连续的内存空间,还有一个特点那就是你一旦声明就不会再改变了

小白: 嗯嗯,这个我知道,数组一旦确定将是固定不变的,哦哦,我知道了,那这里就必须要求指定长度了,不然相当于没创建数组啊,长度为0没意义啊😂

数组在内存中的分配

庆哥: 对的,我们再看这段代码

int[] a = new int[10];

是个怎么回事,首先我们知道了,这是要创建数组吧,长度也指定了,是10,对了这里忘了说了,这个数组是个整型数组,类型是int,为啥要说这个嘞,等会再详细说,先来看图

来吧!给你不一样的数组深入讲解!啥意思嘞?这些个格格就可以看成是内存,一块块的内存,现在我们创建一个长度为10的整型数组,那就需要十块这样的内存空间。

小白: 这里红色的块是啥意思啊?😅

庆哥: 红色啊,就代表已经被使用了的内存空间,看出啥问题了没,现在你创建这样的代码

int[] a = new int[10];

意思就是你告诉内存,“内存那家伙,给我来十块内存空间,记住必须连续的哦😂”,也就是说,数组申请的内存空间是连续分配的,数组中的数据比较矫情,必须一个挨着一个😂

简单聊聊初始化

小白: 嗯嗯,我记得数组的声明不止这一种吧?😉

庆哥: 是的,我们之前介绍的这样叫做动态初始化数组,啥意思嘞,就是指定了长度,但是没有给值,我们看这个

 int[] a = new int[10];
  System.out.println(a[2]);

输出是0,你可以试下,这10个数据都是0,这是默认初始化的值,我们也可以使用这样静态初始化

int[] b = new int[]{1, 2, 3};

啥意思,也就是在创建数组的时候就把值给确定下来,你猜猜这样创建的数组长度是多少?

小白:  这个啊,这里没有给定像10那样的数据啊😂,这个应该是。。。3吧😅,后面大括号有三个数

庆哥: 我们看下这段代码

int[] b = new int[]{1, 2, 3};

        System.out.println(b.length);

这是啥,这是求数组长度的,我们看看输出

来吧!给你不一样的数组深入讲解!被你说对了,像这样的,它会根据你大括号里的数据创建内存空间,也就是说有几个数就申请几个内存,不多不少申请了就固定了

数组变量和数组对象

庆哥:  我们上面已经简单介绍完数组了,那你知道什么是数组变量什么是数组对象吗😂

小白: 我去,晕菜,这俩双胞胎吧🤣

庆哥: 那我来说说,啥是数组变量,看之前的代码

int[] a = new int[10]

这个a其实就是一个数组变量,一个数组变量指向一个数组对象,数组变量其实就是一个引用,存放的是内存地址,也就是引用是与内存地址划等号的,内存地址是给计算机看的,而引用是给我们看的(一个我们比较熟悉的符号),而这个a其实是数组的首地址,指向的数组对象其实就是a[0]这个数组变量对应的数组对象。

那数组对象其实就是内存空间中存放的数值了。

数组初始化是对谁初始化

那我们接着这个数组变量和数组对象来讲讲,数组初始化是对谁进行初始化,其实也很简单,知道了什么是数组变量和数组对象之后,我们就应该知道,数组初始化不是对数组变量初始化,而是对数组对象进行初始化。

所谓的对数组对象初始化,无非就是告诉内存,我要创建一个数组,你得给我分配一块连续的内存。

咋样,明白了吧😁

小白: ok的😎

数组能存储啥😅

庆哥: 好了,以上属于数组的基本知识,不多说了,我们接下来再来说说数组的数据存储类型,还记得之前说的吗?数组中的每个元素都是相同的类型,我们上面是int类型的,啥意思嘞?也就是说啊,你创建什么类型的数组就只能存放什么类型的数据。

比如这样就不行

来吧!给你不一样的数组深入讲解!因为你创建了是个int整型的,所以只能存放整型数据,字符串就不行,想要存放字符串的话那就要创建一个字符串数组

 String[] strings = new String[]{"hello"};

有个小例外

这里啊,是有个例外的 ,我们看这个:

Object[] objects = new Object[10];
        objects[0] = 1;
        objects[1] = "hello";

这个是都可以的,知道为啥不😁

小白: 这个啊,知道,Object可是java中所有类的超类啊😂

庆哥: 正解,好了,咱来简单总结下:

Java中的数组是用来存储同一种数据类型的数据结构,一旦初始化完成,在内存中的空间就已经固定了下来

数组是个对象?

庆哥: 你说数组是不是个对象?😎

小白: 数组是对象?不是说数组不能用new的方式创建吗,那应该不是吧,感觉和平常的对象不一样啊😂

庆哥: 实话告诉你吧,数组啊,其实是个特殊的对象😎,只不过数组比较特殊,它不同于一般的对象,像一般的对象都有特定的java类,比如我这里创建了一个Person类,然后有这个代码:

 Person person = new Person();
        System.out.println(person.getClass().getName());

就是创建一个Person对象,然后得到它的类名,如下

来吧!给你不一样的数组深入讲解!再来看个

Object object = new Object();
        System.out.println(object.getClass().getName());

这个知道吧,它的类名一定是Object,我们看

来吧!给你不一样的数组深入讲解!是吧,我们再来看数组的,它可以这样获得

//数组是特殊的对象,没有对应的类文件,数组类是在运行时产生的,类名很奇怪
        System.out.println(new int[2].getClass().getName());

它这个类是啥嘞

来吧!给你不一样的数组深入讲解!

在这里插入图片描述

这是啥玩意😂

小白: 我去,这里我是不是只要记住,其实数组也是个特殊的对象就行了吧😂、

庆哥: 对的,只需要记住,数组其实也是个对象就行,这可是对数组的深层次理解哦😁,那接下来我们继续说数组的两个让人懵圈的类。

Array和Arrays

对这俩货熟悉吗😂

小白: 很懵圈啊,之前我还想使用Array来创建数组嘞😂

庆哥: 哈哈,使用它创建数组是不行的,话说这俩货是干嘛的啊,太容易让人迷惑了,实际上啊,这俩货的存在都是为了让我们更一步的操作数组的,先来个简单的例子,比如我们创建一个数组

 int[] b = new int[]{1, 2, 3};
        System.out.println(Array.get(b, 1));

看到没,我们平常是使用b[1]来获取下标为1的元素,使用Array就可以像上面那样获取,也就是说Array给我们提供了可以直接操作数组的一些方法,有如下这些:来吧!给你不一样的数组深入讲解!小白: 这就是个类似工具类啊,可以方便我们操作数组是吧😁

庆哥: 对的,还记得我们之前就说过这个Array吗,它的构造方法是私有的,不能实例化,它的方法也都是静态的,可以直接还用类名来调用,就像上面那样,就是为了我们更加方便的操作数组而存在的。

小白: 这样说的话,那这个Arrays是不是类似啊😂

庆哥:  是的,Arrays也是个方便我们操作数组的工具类,只是他们提供的功能有所不同,我们使用Arrays可以实现给数组填充数据,也就是赋值,也可以进行排序啊,进行二分查找啊,截取数组啊之类的😂

小白: 这个提供的功能还不少嘞😁,使用上是不是和Array类似啊

庆哥: 是的,你看,比如说给数组数据进行排序

System.out.println("排序:");

        int[] array1 = new int[]{5, 7, 8, 9, 1, 3, 6};
        Arrays.sort(array1);

看它提供的方法

来吧!给你不一样的数组深入讲解!

在这里插入图片描述

也有很多,需要啥我们用啥就行了

咋样,这样一介绍,是不是发现,其实这俩货也没啥难的啊😂、

小白: 是啊,原来就是两个打辅助的啊😅

数组的特点

庆哥: 到了这里,你是不是能 总结下数组的一些简单特点啦😁

小白: 嗯嗯,数组啊,连续内存分配,可以随机访问,这次刚刚学到的,数组其实是个对象😎,对了,数组还有下标,是从0开始的。

庆哥: 嗯嗯,问题来了,为啥要从0开始,你知道吗?

下标索引为啥从0开始

小白: 这个还真不知道,平常就记着下标是从0开始的了,至于为啥是从0开始还真不知道嘞😂,为啥啊庆哥。

庆哥: 要弄明白这个问题,要看这个图

来吧!给你不一样的数组深入讲解!我们已经知道了,数组的创建需要连续的内存空间,比如这里的整型数组,长度为10,那就再内存开辟了相应的内存空间,在内存空间中,每个内存是有相应的地址的,这个是操作系统干的事,当你申请了内存之后,操作系统会为这块内存地址进行编号。

比如这里申请了一个长度为10的整型数组,我们知道int在java中占4个字节,也就是说一个数据占四个字节的内存,也就是上面的一块.

然后每一块都有相应的内存地址编号,比如0对应的这块,编号是1000-1003,占四个字节嘛,我们接下来结合数组的随机访问,比如我们使用array[0]去访问第一个元素,实际指向的就是1000这个内存地址,这个在数组中也叫作首地址,数组变量array就是指向这个首地址。

这个首地址也叫作base_address,记住这个,然后我们如果要访问下标为1的怎么访问嘞,这里有个寻址公式

array[i] = base_address + i*data_type_size

base_address我们知道是啥了,那data_type_size是啥?其实即使数据类型的字节长度,比如这里的int整型就是4个字节,那data_type_size就是4,我们现在要访问下标为1的数据,代入公式就是:

array[1] = 1000 + 1*4 = 1004

看下,是不是刚好定位到下标为1的那块内存的位置。

你想想,如果索引从1开始,那寻址供视是不是就变成了

array[i] = base_address + (i-1)*data_type_size

这就要多一步操作,浪费性能啊😂

咋样明白不😅

小白: 嗯嗯,原来是这么回事,终于学会了😎

数组的增删改查

庆哥: 嗯嗯,那我们再来看看数组的增删改查,也就是对数组进行的一些基本操作,首首先看看数组增加,我们还看着这个图来说

来吧!给你不一样的数组深入讲解!如果我们要增加一个元素的话,怎么办?

小白: 这分几种情况吧,插在最前面,中间和最后。

庆哥: 如果是插在中间呢?发现啥问题没?😎

小白: 嗯。。我想想。。数组内存是连续分配的,那要插入一个新的元素,那岂不是要把当前位置的元素以及后面的元素全部后移了,这样才能腾出位置插入当前元素吧😂

庆哥: 对的,所以对于数组,不仅是插入,删除也是同样的道理,如果不是尾部操作,都需要进行数组挪动操作。

小白: 那这个就费劲了😂

庆哥: 是啊,所以数组啊,插入删除效率并不高,最坏的情况,时间复杂度是O(n),好的情况那就是尾部操作,那就是O(1)了,这个知道吧😀

小白: 嗯嗯,知道,那查找效率是不是高啊

庆哥: 这里我觉得大家都有个误区,什么嘞,数组如果是使用下标访问,那自然效率高,可是我们平常查找的话是根据数值也不都是下标啊,这样就需要遍历数组找到我们想要的,这个要明白

小白: 是啊,你这样一说,我倒知道了

数组扩容

庆哥: 对了,想一下,如果数组满了咋办😎

小白: 这个啊,数组满了,就无法插入新的元素,这样的话就需要对数组扩容,这个扩容,我想想,数组一旦初始化完成,就是固定不变得,这样的话,是不是需要新创建一个数组啊😂

庆哥: 对的,数组一旦初始化完成,在内存中的空间就已经固定了下来,即使某个元素被清空,但其所占的空间依然是保留的,因此数组长度是不能被改变的,要想改变数组的空间就必须进行数组扩容。

小白: 那这个是不是就需要把原数组的数据全部复制过去啊

庆哥: 对的,有如下简单代码来吧!给你不一样的数组深入讲解!小白: 哦哦,明白了😎

完!!!

ps:数组这块怎么说嘞,反正写的有点痛苦😂,现在已经是夜里两点了,先到这吧,如有问题,欢迎大家留言讨论!

感谢阅读  更多高质量编程视频www.shangyepingtai.xin

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!