JavaWeb(3):浅谈集合(上)
抛开很多复杂高深的技术不谈,我们会发现其实编程不外乎传输数据和处理数据。所以才有下面这句话:
程序 = 数据结构 + 算法
这里不评判这句话是否正确,每个人都有自己的看法。但是不论如何,我们都无法否认编程的本质就是和数据打交道。在现实生活中,我们从采购点买入原料,装入【一个个货柜】运往加工厂,然后再把加工完毕的商品放进【一个个包装盒】打发上市。而在编程的世界里,我们也需要“货柜”去“装载”我们的数据。幸运的是,这些“货柜”已经不用我们去做了。为了适应实际编程的多种需求,Java已经为我们创造了多种多样的容器供我们选择——集合。
集合体系
Collection
|--List
|--ArrayList
|--LinkedList
|--Vector
|--Set
|--HashSet
|--TreeSet
Map
|--HashMap
|--TreeMap通过学习Java中的集合,我们可以接触到几种不同的数据结构(当然,要往深了说,学问可就大了。要不然也不会有《数据结构》这门课)。正因为几种容器底层的数据结构不同,才使得这些容器各自有着不同的一些特性。比如某些容器允许数据重复,而另一些容器则无法存入重复数据。又比如有些容器保证数据存入和取出的顺序永远一致,而另一些容器则不保证这一点。
在开始学习集合之前,我们必须搞明白以下两点:
- 为什么需要集合
- 了解Object的部分方法
为什么需要集合?
似乎我们在上面已经回答过这个问题:为了装载数据。但是我们之前已经学过数组,它也是一种容器,用它不行吗,非要搞个集合出来?

什么?你说它的数据太单薄、太散乱,不能体现数据的相互关系?没事,我们可以把数据封装到一个个对象中,然后把对象的引用存入数组,这样就有了对象数组啦!

啥?老黄因为肾虚被他女朋友甩了?不哭,来,添把凳子坐下来慢慢聊。此时我们才发现,特么已经没有老黄的座位了。0~7号,已经坐满单身狗。尴尬的情况也发生在编程世界。在Java中,数组一旦创建,长度就是固定的,在容量上无法对数据的增删做出相应改变——变长/缩短(除非新建数组并复制数据)。在某些情况下,这显然无法满足我们的需求。所以,集合应运而生。
集合与数组的比较
A:长度区别
数组的长度固定
集合的长度可变B:内容不同
数组存储的是同一种类型的元素(比如都是int)
集合可以存储不同类型的元素(当然,一般不会这样做)C:元素的数据类型
数组可以存储基本数据类型,也可以存储引用数据类型
集合只能存储引用数据类型
也就是说,集合只存对象(引用),而且长度可变。目前只需知道集合为什么比数组合适,不要去了解集合具体是什么。
【题外话】
其实我个人认为,所谓集合长度可变,其实也是表象。以ArrayList为例,查看源码可以知道,它有3个构造方法:空参构造器(默认长度10),可指定初始化长度的构造器,可接收另一个集合的构造器。
而它内在的机制是:初始化大小为10,当添加过程中检测到容量不够时,ArrayList会自动扩容。

那么为什么数组败给了集合呢?因为数组需要我们手动扩容,不方便。


了解Object类的部分方法
Object大概属于那种“熟悉的陌生类”。虽然我们日常使用的所有类都默认继承它(毕老师说就像上帝一样的存在),但是我们却“看不到”它,平时用到它的几率更是少之又少。由于集合中的几个重要知识点,比如重写hashCode()和equals()方法,比如打印对象时默认调用的toString()方法,又比如我们上一篇提到的反射可能用到的getClass()方法,这些方法都是继承自父类——Object类。所以我们有必要走进它,了解它。

推荐大家打开IDE,自己点进去看一下。没那么神秘。这里除了equals()、hashCode()、toString(),其他方法下面不做展开

看了上面的部分源码分析后会发现,我们最关心的三个方法:equals(),hashCode(),toString()中,hashCode()是最关键也是最难的。
equals()方法最简单,底层就是用"=="比较两个对象的地址值。但我们说过,即使同一个类相同数据的两个对象,比如:
Student s1 = new Student("老黄", 26);
Student s2 = new Student("老黄", 26);如果Student类不重写从Object继承来的equals()方法,那么s1.equals(s2)结果就是false。因为前后两次new对象,都在堆内存中开辟了空间,地址值肯定不同。这样的比较是没有任何意义的。因为实际编程中,我们倾向于把内容相同、而不是对象地址值相同的对象认定为重复。比如我已经存了一个new Person("周杰伦", 39),下一个new Person("周杰伦", 39)就不能再存进来。

而toString()方法就更水了,就是简单地调用getClass()和hashCode()拼凑出一点类信息:itcast.cn.test.Student@42552c。这种信息没有任何价值,所以我们一般推荐子类重写toString():
@Override
public String toString() {
return "test [age=" + age + ", name=" + name + "]";
}以上就是学习集合前必须了解的一点背景知识。有个印象即可,后面还会提到。
翻开集合框架源码,author一栏写着Josh Bloch
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。