JAVA小白系列之第三个分支:Collection容器

那么,在了解了变量和面向对象相关知识后,我们来了解下容器的概念,通过这一节你可以学到:

  1. 数组
  2. 集合
  3. 集合的框架概览
  4. 数组和集合的差异
  • 容器的概念

先回顾一下变量的概念,变量是计算机用来保存数据的一个地方【桶】,这个桶可以装不同大小的数据、不同类型的数据,所以这个桶便有了大小和类型。那么有了这个概念之后来看看容器,先给出结论----容器就是一组变量的集合,所以我们称容器就是为集合,用一张图来解释:

 

一言以蔽之:集合里就是一堆变量,他们有着相同数据类型和大小。

  • 数组

数组从字面意思上来看,就是一组数据对吧,事实上就是这样的,它就代表了一个容器,也就是包含了一组相同类型和大小的数据,先来看看java的数组定义:

  1. 数组类型[] 数组名=new 数组类型[数组大小];
  2. 数组类型[] 数组名={数组值};
  3. 数组类型[] 数组名=new 数组类型[]{数组值};

这里用int这个类型来演示:

int[] arr_1={1,2,3};

int[] arr_2=new int[3];

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

上面的int[] arr_1;就是上一节说的声明了一个引用,也就是说我这个arr_1指向的是一个数组,而后面的{}、new int[3]、new int[] {1,2,3}就是这个数组的内容,不同的是{}、new int[] {1,2,3}他们两个对这个数组进行了创建并且初始化,而new int[3]只进行了数组创建而没有对数组里的数据进行初始化,只是保留了每个不同类型的初始值:byte、short、int初始值0,long初始值0L,float初始值0.0f,double初始值0.0d,char初始值’’[‘/u0000’这里记住就好如果想要知道为何是这样请看看unicode编码相关~],boolean初始值flase。因为这里是int所以如果我没初始化里面的所有数据都是0。

Ok这就是java的数组,是不是很简单,只需要知道容器是什么,和变量的区别是什么,这样面试就没问题了~

  • 集合的框架

了解了数组之后我们再来看看集合,老方法,先看看字面意思,就是一堆东西的聚集嘛,这个其实也是个容器,但是问题了:有了数组为何还需要集合呢?是这样的因为数组太过简单,正因为他的简单就意味着很多场景不合适,比如由于数组的长度在声明的时候就确定了不能再扩大,如果我的数据多少未知怎么办?我如果创建一个小容量的数组那么不够装,如果太大就浪费空间对吧,这样我就需要需要另外一种容器能够扩容的。再比如我需要我容器里的数据能够去重,那么数组也是不能胜任的。因此我们需要另外一些容器来为我们服务,这样集合就应运而生了。

那么先来看看JAVA的集合怎么定义的:

集合类型 集合名=new 集合类型();//如果有小伙伴提前学了,了解泛型,那么也不要惊讶我为何这么定义,毕竟得关注于集合本身,小白可能不懂泛型,这个在后面一节我再详细解释,这里不了解泛型没关系~

来看看实际代码:

List list=new ArrayList();

Set set=new HashSet();

....

以上就是java的集合定义,有同学会说,这不就是上节说的面向对象吗?毕竟new就是用来创建对象的嘛,那么前面的List和后面的ArrayList是不是就构成了多态呢,前面有讲过,所以这里是不是就是个向上转型呢?同样下面的set也是如此。那么这就是java的集合定义,那么我们说了集合的出现是为了解决数组的局限,因为他们都是容器,所以数组和集合的共同点就是有着相同大小和数据类型【当然如果没有泛型这个规则会被打破,这个后面泛型一节细说,这里大家先这么认为就行了】。

那么这里我们来看看java是怎么构建这样一个体系的,要想摸透这样一个体系,我们必须去翻阅源码。首先我需要确保大家明白两个知识点,因为正是这两位的存在才让java的面向对象体系变得完整:

【如果懂得直接跳到分割线以下】

  1. 接口

Interface 接口名{抽象方法}//java用interface来声明一个接口

  1. 抽象类

Abstract Class 类名{实例方法或抽象方法}//用abstract关键字来表明这个类是抽象类

接口和抽象类都是对对象的行为的抽象。只不过不同的是,接口里的方法必须全是抽象的,公有的【jdk1.8除外】,接口的变量必须是静态的、共有的、final的,而抽象类可以有实现的方法和实例变量等等,他也可以有抽象方法,不能够new对象,嗯这就是对象和接口,如果有人问你他两的优缺点在哪里我想上面就是答案,并且由于java类单继承,接口可以多实现,导致了如果你继承了一个类那么你就不能再继承别的类了,这也是抽象类的局限。

那么他们的应用场景在哪?看上面一段的第一句话,行为的抽象,这是什么意思呢,还记得为什么有继承和多态吧,就是让不同对象有多种形态,但是是什么形态我是不是并不知道具体的形态干什么对吧,我第一步我需要的是抽象成一个方法:public void method();并没有实现体:public void method(){这里是实现体};,而我只需要声明我有这个行为,我并不知道具体的形态是怎么去做这个行为的,这就是抽象,就比如我用一个接口:

Interface Humen{

Public void speak();

Public void see();

}

声明了一个人的接口,也就是抽象出了人有说话和看的行为,我并不知道具体的人是怎么说怎么看的,这也就是行为的抽象,那么我可以定义不同的人怎么说怎么看:

Public class ChinaHumen Implements Humen{

Public void speak(){

//中国人说

}

Public void see(){

//中国人看

}

 

}

Public class AmericaHumen Implements Humen{

Public void speak(){

//美国人说

}

Public void see(){

//美国人看

}

 

}

...

对吧,不同的人有着不同的看,而我们只需要用Humen humen=new XXXHumen();这样我就不用管谁来说和看了我只需要这是个人,管他是中国人还是美国人。

------------------------------------------------华丽分割线---------------------------------------------------

Ok那么我们直接上ArrayList的源码:

public class ArrayList<E> extends AbstractList<E>

implements List<E>, RandomAccess, Cloneable, java.io.Serializable

那么这就是ArrayList这个集合类的源码,上面的尖括号你可以忽略,主要看extends AbstractList表明了这个类继承了这个抽象类【Abstract抽象的意思】,那么来继续跟进:

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E>

可以看到又继承了AbstractCollection并且看到还实现了一个接口List,那么继续跟进AbstractCollection抽象类:

public abstract class AbstractCollection<E> implements Collection<E>

List接口:

public interface List<E> extends Collection<E>

从上面有可以发现不管是抽象类AbstractCollection也好还是接口List也好,最终回归到Collection这个接口对吧,来看看它长什么样:

public interface Collection<E> extends Iterable<E>

那么可以看到这个接口呢最后继承了Iterable,那么这里不讲Iterable留到后面讲,关注点在于集合而不是迭代器不是?

再继续之前,我觉得有必要进行讲解一下看源码的步骤:

  1. 顶层接口
  2. 逐步向下
  3. 整理继承体系
  4. 接口实现细节

这里解释下为何我选择这么看接口的过程,首先我们知道接口是对于对象行为的抽象,也就是我可以通过接口看到我这个对象所具有的行为而不用去管对象具体是怎么去做这个行为的,这样我能掌握到大体的框架,然后在了解了有这些属性后我们再继续去深入方法研究具体的实现算法,这样就能更好的掌握其中的知识点。打个比方说,每个接口都是一个功能模块,我们可以通过接口的继承来把各个功能模块组合起来,这样形成了一个多功能的接口,比如上面的List接口继承了Collection接口,而为何我要从顶层接口看呢?这是因为你先掌握每个单独的功能,然后再往下看功能的组合接口这样有利于形成一个继承关系图~方便记忆,也更好的能够从简到容易的去理解每个功能接口提供的功能方法~

在看完ArrayList的源码后我们在来看看HashSet集合的继承体系:

1、HashSet:public class HashSet<E> extends AbstractSet<E> implements Set<E>, Cloneable, java.io.Serializable

2、AbstractSet:public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E>

3、Set:public interface Set<E> extends Collection<E>

看看最终是不是又回到了Collection接口,这点和ArrayList很相似,万祖归宗,不管List还是Set最后都属于Collection接口,那么我是不是就可以这样说Collection是总接口提供了集合的基本功能抽象,然后Set接口和List接口分别继承了Collection的接口并且提供了独有的功能,而ArrayList和HashSet则分别是List和Set的具体实现,那么这样集合这个结构就明了啦,来用一个UML图来表示:【不懂UML类图的百度下五分钟搞定】

 

好的,这一节我们了解了什么是容器,Collection集合的继承图以及了解了他们常用的两个具体实现类:ArrayList和HashSet,并且学会如何去看一个源码的步骤,那么同样,我们来把这一节的知识挂上知识树。

 

预告:下一节将会进一步进入ArrayList的细节来进行具体的List的抽象实现的细节来剖析源码,并且会介绍数据结构的基本知识~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值