Java学习里程-----Java基础_8数组与集合

落花浮王杯 提交于 2019-12-30 03:01:36

一、数组

数组我们上一讲中说数据结构的时候有提到过,但是那个是一维数组,相应的我们还有多维数组。下面我们来说说数组如何添加、如何遍历。

我们可以使用for循环,循环的条件是不超过数组的长度。数组的长度是3,我们可以用数组点length这个获取到数组的长度。

这里我们还得说一个重要的东西。再来看代码

可能有一些同学看出来了,当a的值是0的时候,i[0] = 1 。当a的值是1的时候,i[1]的值是2。

数组中,第一个元素的开始位置是0,而不是1,为啥要这么定义啊,为啥不从1开始?这个就是我前面说的,这东西是外国人定义的,不是我们中国人定义的,人家就是喜欢从0开始,没办法,我们就只能也是从0开始。

当然,除去这样的用for循环来遍历,我们再引入另外一种循环,叫foreach循环,这个之所以前面没有说,是因为怕你们接受不了,所以我就放在数组这里了。

foreach 循环用法是这样滴:

看,是不是方便许多?大家可以练习一下,我来解释这些个东西。

for(int a : i)foreach没有去从新弄个关键字,而是用的for这个关键字,然后括号中写的就是要遍历的对象。

int 你要遍历的数组是int类型的数组,所以就使用int,如果数组是char,那么这里的int 需要换成char。

a 这个是给每一个循环出来的结果赋值为a,第一次循环开始执行的时候,将i[0]赋值给a变量,那么a就等于i[0],第二次再将i[1]赋值给a,这时候,a就不是i[0]了,因为是从新定义的一个a,不是用的第一次的a。这个也就是说明,每一次循环,都会创建一个新的a。

i就是你要遍历的对象。

 

下面我们来说多维数组,我们就来说二维数组,下面是它的格式

类型 arr =new 类型[]{{element1,element2},{element1,element2},{element1,element2}};

来,上代码

瞅瞅,这个就是一个二维数组,那么如何去循环遍历呢?

我们是这样去实现,第一个循环先读出来{1,2,3} {4,5,6} ..,然后第二个循环再去读{1,2,3}中的1 2 3 。

上代码

是不是,就是将我们第一个循环读取到的集合,再去循环一次。大家要多多联系。三维呢,就是相当于再嵌套一次循环。

二、集合

集合相对数组来说,我觉得是比数组要高级一些了。

Java集合就像一个容器,可以存储任何类型的数据,也可以结合泛型来存储具体的类型对象。

集合类是Java数据结构的实现。它允许以各种方式将元素分组,并定义了各种使这些元素更容易操作的方法。

我们呢,主要讲三个我们常用的集合:List集合、Set集合、Map集合

List集合:

List是java.util包下面一个重要内容,它呢是一个接口(后面我来将接口这些,先看),接口呢,不能直接实例化,也就是说,无法直接用List,需要找到子类的实现,然后才能去使用。

list是一种有序集合,可对其中每个元素的插入位置进行精确地控制,可以通过索引来访问元素,遍历元素。

而List下面有两种实现方式,一个是ArrayList,一种是LinkedList,下面我们来说一下这两个实现类。

ArrayList:

ArrayList底层通过数组实现,随着元素的增加而动态扩容。

它继承AbstractList,实现了List, RandomAccess, Cloneable, Serializable接口。

(1)ArrayList实现List接口,得到了List集合框架基础功能;
(2)ArrayList实现RandomAccess接口,获得了快速随机访问存储元素的功能,RandomAccess是一个标记接口,没有任何方法;
(3)ArrayList实现Cloneable接口,得到了clone()方法,可以实现克隆功能;(这个我们以后再将)
(4)ArrayList实现Serializable接口,表示可以被序列化,通过序列化去传输,典型的应用就是hessian协议。(序列化与反序列化我们同样放到以后来说)

所以ArrayList有如下特点:

1.容量不固定,随着容量的增加而动态扩容

2.有序集合(插入的顺序==输出的顺序)

3.插入的元素可以为null

4.增查询速度快, 增删元素慢;(相对于LinkedList来说)

5.线程不安全

LinkedList:

LinkedList底层通过链表来实现,随着元素的增加不断向链表的后端增加节点。说具体一点,它是一个双向链表,每一个节点都拥有指向前后节点的引用。相比ArrayList,它随机访问的效率更低。

它继承AbstractSequentialList,实现了List, Deque, Cloneable, Serializable接口。

LinkedList实现Deque,Deque 是一个双向队列,也就是既可以先入先出,又可以先入后出,说简单些就是既可以在头部添加元素,也可以在尾部添加元素;

其他实现的接口功能都一样。看上面的ArrayList即可。

它的特点:(相对于ArrayList来说)

 1.查询速度慢, 增删元素快

 

我们可以看到,每一种list集合的实现类因为底层实现的机制不一样, 导致功能也不相同,所以我们使用者需要了解,深入的知道区别,这样才能发挥它们的长处,总不能用LinkedList去弄一个经常被查看的吧。

下面我们用代码实现一下:

创建一个list集合,让它实现ArrayList,并且调用add方法添加三个值,然后输出。

然后调用remove方法,去掉第二个,然后输出,我们发现python没有了,这个呢和数组是一样的,第一个Java是0,c++是1。

我们可以发现,list.size()可以输出集合的长度。

相同的,它也可以使用for循环,利用.get(i) 获取到该位置下的值。

Set集合:

Set集合和list集合差不多,但它特征是插入无序,不可指定位置访问。也就是说,list可以通过get(i)获取,只要是一个固定好的集合,不管什么时候获取,都可以获取到同一个值,但是Set集合缺做不到,为啥呢,这个也得去分析它底层的代码才可以知道。

而且,Set集合中不会存在两个相同的值。等一下我们来比对。

Set呢也同样是接口,它常用的实现类有两个,一个是HashSet,另外一个是TreeSet。(说实话,后面内个我也不咋用)

我们用代码创建这两个集合:

然后我来说说他们的区别

HashSet:

1.不能保证元素的排列顺序,顺序有可能发生变化

2.集合元素可以是null,但只能放入一个null

HashSet呢,是实现了Hash表的,也就是说,值是唯一的,不会出现重复的,虽然说我们存放了一个值,但是它在保存的时候是存放的两个值,一个是我们要存放的,另外一个是这个值的hashcode的值。而这个hashcode是唯一的,并且和存放的值是一对一的,所以,不可能出现一个锁出现两种钥匙。

说的可能有点蒙,我们来上代码

我们命名存放了两个1,但是大小却只有一个。然后我们再来看一个

我们将其中的一个1改变成2,发现,诶,这个大小是2。

还有就是它的无序性:

看我插入的顺序,但是输出的顺序缺不一样。

它的遍历方式和List一样,都是使用for循环遍历。

等你学到一定程度的时候,可以去看看这个底层的源码,我们初学,尽量不要研究那么深,不然走火入魔。。悠着点来

TreeSet:

TreeSet可以确保集合元素处于排序状态。TreeSet支持两种排序方式,自然排序 和定制排序,其中自然排序为默认的排序方式。

TreeSet 是二差树实现的,Treeset中的数据是自动排好序的,不允许放入null值。

下面我们上代码,我们来看一下:

Map集合:

Map集合呢,是一种键-值对(key-value)存储的集合,和上面HashSet的底层有点关系,有兴趣的同学可以自己去查看哦。

这种存储方式是什么意思,就好比钥匙和锁一样,一个key对应一个value,但一个value可能有多个key,而我们通过key来获取value的值。

对了,Map集合也是接口,当然,它也有实现了它的方法,和Set集合类似。HashMap 类和 TreeMap 类。

下面我们来用一下:

HashMap:

定义两个Map,分别让两种子类去实现。然后我们用HashMap的这个去操作。

可以看到,我们插入了两个key为2的value不同的值,但是,key为2的的value值缺是Go,C++这个值呢?

其实,是被覆盖掉了,所以,在一个Map集合中,不可能出现两个key相同的值,如果强行插入一个key相同的,那么,上一个就会被覆盖掉的。

虽说key不能相同,但是value可以。

TreeMap:

好吧,我是测试过了,好像和HashMap差不多。

同学们可以自行研究一下。

 

Map的遍历比较特殊,我们来说一下:

这个里面引入了迭代器,将map中的值放入到迭代器中,然后判断迭代器是不是有下一个,如果有,就去找他们的每一个key和每一个value,然后输出。

当然,遍历这些集合不是唯一,需要看项目需要,然后我们去选择,有兴趣的同学可以研究一下其他的方式哦!

 

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