一、数组
数组我们上一讲中说数据结构的时候有提到过,但是那个是一维数组,相应的我们还有多维数组。下面我们来说说数组如何添加、如何遍历。
我们可以使用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,然后输出。
当然,遍历这些集合不是唯一,需要看项目需要,然后我们去选择,有兴趣的同学可以研究一下其他的方式哦!
来源:CSDN
作者:他 他 = new 他()
链接:https://blog.csdn.net/weixin_45908370/article/details/103752525