1.集合简介和例子

Collection,集合。和数学定义中的集合类似,把很多元素放在一个容器中,方便我们存放结果/查找等操作。

Collection集合实际上是很多形式集合的一个抽象。

例如十九大就要召开,那么到人民大会堂与会的人就是一个集合 ,这个集合里装载了许多元素,每个元素就是一个人大代表。

再比如北京的全聚德烤鸭非常出名,每天都有人排队购买,这个队也是一个集合。

上面这两个例子就展示了两个不同的集合,人大代表的集合其实就是一个简单的聚合,把若干元素集中在一起。第二个例子,排队就具有比较鲜明的特征了,先到的人可以先买到,有一个顺序的关系。

2.面向对象思想中的“抽象”

Colletion是一个抽象,Java编程设计中,抽象是很常用也很重要的方法。

那么,抽象是什么?

抽象,先从语文的角度看一下这个词汇,按照《咬文嚼字》拆解词语的方式,“抽象”,抽:抽取,抽出;象:现象,形象,象征,特征。现在把两个字组合起来,抽象的意思就是“抽取特征”。它的反义词是具体。

Collection集合是一种抽象。就像衬衫,裤子,内衣都可以称作衣服一样 ,衣服就是一种抽象。而之后要了解的数组(Array),链表(List),Set,队列(Queue),栈(Stack),等都是集合的一种。这些不同的集合,就如不同的衣服一样,有着不同的作用,然而他们都是集合。

Collection在Java中是一个接口,接口可以简单的理解为一种规范或者协议。

接口中定义了一些条款,所有遵守接口协议的人,都必须按照我给出的条款而必须具有某种功能。例如Collection中规定,首先能够成为一个容器,用来盛放一些数据,其次集合要有添加和删除元素的功能等等。于是集合的这些不同形式例如 数组/链表/队列 都可以放置数据,并且有添加元素和删除元素的功能。

也就是说,Collection接口描述了作为一个集合要拥有的特征,但是Collection接口本身并没有这些功能,这就是抽象,而数组,链表这些具体的集合拥有Collection的规定的特征,且具体地表示了一类集合,并能够执行操作。

例如生物学上的分类,对于每一个分类都是抽象:界,门,纲,目,科,属,种。例如对于人来说,人其实就是一个抽象,远到盘古夸父,秦皇汉武,唐宗宋祖,近到毛邓,爱因斯坦,卓别林,这里的每个伟人都是人的具体实现。人其实是属的名称,动物界,脊索动物门,脊椎动物亚门,哺乳纲,灵长目,人科,人属,智人种。很久之前,也存在其他的人种,到如今只剩下智人,再无奈也是物竞天择的结果。

楼已歪,扶正继续。

智人种给出了这么一个定义,脑容量大,直立行走,可以制造工具等。但是“人”本身只是一个一类东西的统称,规定了作为一个人应该有什么样的功能和属性,而真正能够使用这些功能和属性的,是我们每个具体的人。而对于每一个读者,都是动物这个抽象下的具体,你可以想象,你和天空中刚刚飞过的那只鸟,你膝盖上卧着的猫,甚至厕所里的蟑螂都实现了动物这个接口,而你和电脑旁的仙人掌,绿萝,口腔里的细菌却没有什么动物界交集。然而所有这些,又都实现了另一个更抽象的接口,生物。

没有最抽象,只有更抽象——也许这句话才是对“抽象”最好的解释。

我们应该如何抽象?

抽象的过程就是抽取特征的过程。例如我想要一块肉,也就是说我描述了肉的基本特征,需要来自可食用的动物,并且经过加工之后吃起来很香,当然这些是特征描述,也是某种意义的限制,限制了肉不仅要健康可食用,而且要好吃。脱离了案牍劳形,脱离了嘈杂忙乱,打电话给母亲:我想吃肉。于是,红烧肉,西红柿炖牛腩,小鸡炖蘑菇,糖醋鱼等等。显然,我说吃肉,只是一个抽象的表述,母亲根据我的喜好,给出了多个具体的肉的实现。

Java里的思想也是这样,所有的Java类都继承于Object类,就像所有具有生命的东西都是生物一样。抽象,使得Java语言,更能描述我们熟知的事物,使其更能贴近我们的语言,而不是冰冷的机器和陌生的二进制数字。

3.集合中最常见的两种结构——数组和链表

最常用的集合有数组,链表,Set,队列,栈,还有vector,vector在这里不做介绍。

首先举个例子说明数组和链表的区别。

数据在内存里的存储方式,非常类似我们在一张田字格的纸张上书写汉字。

通常我们会从头开始,一个格子一个格子地按顺序写下去。就像左侧图片所示,在一段连续的田字格内写一行汉字。这个情形和数组非常的相似,数组也是在内存中分配了一段连续的空间用来存储数据。例如这段空间中存储了四个汉字“我爱红旗”。

而链表则相对嚣张跋扈一些,我自己的纸张,为什么不能随意写呢。但是问题也是显而易见的,如果我想让别人也看懂,那我必须将顺序标识出来,于是我不得不加了个箭头,只要按照箭头的方向就可以读了。当我想在存放链表的空间内再存放一个数组是比较困难的,因为我很难再找到一段比较长的连续空间。这样对比起来数组更有优势,数组更节省空间,数组不需要关心下一个汉字的位置,只要连续读下去就可以了。数组空间的紧凑为将来数据的存放也提供了很好环境。当然无论是数组还是链表,我都需要知道第一个字从哪里开始,所以我用一个标识来标记开头,即数据存储的起始位置。

从空间上看,数组明显是比较好的存储结构,也是日常我们使用最多的数据结构。

但是现在我发现,我不小心写错了这个句子,我本来是要写“我爱五星红旗”,漏掉了两个字"五星"。作为一个不折不扣的爱国青年,我迫不及待地希望把这两个字加上去。下面分别看下两个数据结构的操作。

对于数组,好麻烦。假设我用铅笔写的,我需要把“红旗”两个字擦掉,然后在原来红旗的位置上写上五星。然后把“红旗”往后移,放在五星的后面。分解一下操作:首先我需要在插入“五星”的地方之后的所有汉字(这里是“红旗”)移除,然后我把“五星”两个字写进去,最后把之前移除的汉字“红旗”再追加到五星的后面。好麻烦是不是。。。

对于链表,反正我随便都能写,我随便挑两个我喜欢的位置,写上五星,然后把箭头的顺序稍微调整一下就够了,是不是很方便?

于是数组和链表的区别和优劣势就显而易见了。使用的时候,根据不同的场景选择对应的存储结构,如果只用来存放和查询数据,无疑数组更快,又不浪费空间。如果我要频繁地增加删除,当然链表更快。java中的队列Queue就是使用链表LinkedList来实现,入队和出队就是添加和删除的操作。

上面的介绍,基本属于科普了。现在整点干货出来仍然有点早,继续更深入地科普一下。

4.常见集合详细描述及其用法

java中简单数组和C/C++语言中是一样的。当然Java语言的特性封装、继承、多态中封装的特点为我们提供了极大的方便,JDK中对数组进行封装,方便我们进行遍历/查询/更新/删除等操作。

数组

在JDK中,数组的封装类为ArrayList。

首先看下一般的未封装数组。

数组,不是一组数字,而是一组数据。

在编码过程中,所有的变量一般都会有以下几个步骤:声明,初始化,赋值。

想象以下我们在田字格中书写一些内容。现在我想写一首诗,那么我可能书写的内容是汉字。我会背圆周率小数点后1000位,我想写圆周率炫耀一下我牛逼到惊人的记忆力,那么我书写的内容就是数字。我现在没什么事,就想学达芬奇画鸡蛋,学梵高乱抹色彩,学毕加索搞一搞抽象画,那么我书写的内容就是一幅画,至少呈现了某种奇特的形状。

假设我有一个书童,现在我突然要作诗,我对书童说,给我取文房四宝来。书童拿来文房四宝,问道:“少爷,您是要写诗还是要作画?”。“写诗”。“您是写哪种诗?”。我想着我要写的得意诗句,沉吟了下,说:“七言绝句。” 书童取出一副长七寸,宽五寸的纸放在我面前。我蘸足了墨,把第一行的标题写下:“贾生”。我要写的这个人,是贾谊,汉代名士,却郁郁不得志。念及此,挥笔从第二行开始写道,“宣室求贤访逐臣”,第三行,“贾生才调更无伦”,第四行“可怜夜半虚前席”,第五行,“不问苍生问鬼神”。

书童为什么这么问,因为书童想知道他需要为我装备多大的纸张,避免纸张的浪费。作为程序员,永远要把自己当做一个穷酸秀才,内存的使用永远要寸土寸金。即使我家财万贯,但水滴石穿,绳锯木断,积少成多的道理谁都懂。

想象书童就是电脑(更确切的说是JVM,Java虚拟机),纸张就是内存。我要告诉书童,我写诗,于是书童知道我是写字。这就是声明。我声明我要写一些字,即Char字符类型。用代码表示:

char[] words; // 声明类型

如果我想写一堆数字来记账,那么声明就会变成 int[] numbers;

然后书童问了,你要写什么诗句,答曰:七言绝句。书童知道我绝对不是标题党,题目不会搞得比诗句还长。于是他认为我一个小楷占一寸见方大小,七言绝句,四行,每行七个字。28个字,标题给留上一行也够了,于是他给了一个长七寸,宽五寸的纸张,也就是能写35个字。

这个过程,就是初始化,初始化的作用有两个,一个是确定大小,另一个是赋上初始值。这里的作用主要是确定大小。

于是开始初始化,用代码表示:

words = new char[35]; // 初始化

 初始化了35的空间,保证存储空间够用的前提下又不浪费空间。

当然,声明和初始化是可以一起进行的,将以上两步合在一起。

char [] words = new char[35]; // 声明并初始化一个长度为35的char数组 

最后,我开始作诗了。我先写标题。

char[0] = '贾';
char[1] = '生';

写完标题的我,突然发现了一个非常严重的问题。我写诗之前必然胸有成竹,写诗我想一气呵成。这么一个字一个字的赋值,何时是个头。估计也写不出精彩的诗句了吧。于是我突然想,一行是一句诗,也就是一个字符串,加上标题,我用5个字符串,即5个String就可以了。于是我更改了声明,并初始化如下:

String[] words = new String[5];

 然后,我一气呵成地完成了这首诗:

words[0] = "贾生";
words[1] = "宣室求贤访逐臣";
words[2] = "贾生才调更无伦";
words[3] = "可怜夜半虚前席";
words[4] = "不问苍生问鬼神";

一气呵成,书童拍手不迭,叫道:“好诗!好诗!”。

注意一个区别:char是java中的基本类型,每个char只能装下一个字符,字符可以是字母,汉字,数字,也可以是各种标点,但是编码形式,是用单引号。而String不是基本类型,可以表示一个字符串,长度不限(当然不是绝对完全的不限),字符串的形式是用双引号括起。

我们看下数组的声明方式。

words是变量名,初始化大小的时候,要使用new,在java中,new的意义是申请空间。也就是说,我向书童索要一个足够我写下一首七言绝句的纸张。

然后为数组赋值,准确的说是为数组的元素赋值。数组首先是一个连续空间上的集合。数组的第一个元素的下标是0,不是1。

对于数组下标从0开始有很多原因和说法,当然我认为最合理的解释是偏移量。正如上面介绍的“我爱五星红旗” 的例子,有一个开始位置的标记,这个开始是“我”这个汉字的位置,“我”这个字相对于开始位置它的位置没有加1,它就在初始位置,就是第0个,而“爱”这个字,相对于初始位置,显然是在初始位置的后面1位,“五”是在初始位置后的第2位。与之对应,数组的第一个元素必然是从0开始,然后最后一个元素所属的下标,就是数组的长度减1,因为是从0开始的。就如相对论在物理学的应用,没有绝对的静止。在内存中没有绝对的位置,只有相对的位置,相对与开始位置是第几个。因此,将与开始位置的相对距离,作为数组的下标无疑是一种非常明智的做法。

数组的声明初始化方式很简单。在类型后面加方括号[]即表示了一个数组。

Java 集合Collection——初学者参考,高手慎入(未完待续)的更多相关文章

  1. day9集合以及这段时间的总结 未完待续

    随笔: # 可变类型:# 列表(可以存放多个值,可以按索引取值,是有序的),# 字典(字典里面是KEY:VALUE类型,key必须是不可变类型,不能按索引取值 因为它们是无序的,按KEY取值),# 集 ...

  2. Java方法总结与源码解析(未完待续)

    使用StringTokenizer去掉字符串中的空格 public class StringTo { public static void main(String[] args){ String te ...

  3. java关于null的介绍及比较问题..未完待续

    非对象比较内容,用== 对象比较内容,用相应的方法比如equais. demo1

  4. 2017-2-17,c#基础,输入输出,定义变量,变量赋值,int.Parse的基础理解,在本的初学者也能看懂(未完待续)

    计算机是死板的固定的,人是活跃的开放的,初学c#第一天给我的感觉就是:用人活跃开放式的思维去与呆萌的计算机沟通,摸清脾气,有利于双方深入合作,这也是今晚的教训,细心,仔细,大胆 c#基础 1.Hell ...

  5. Java开发中的23+2种设计模式学习个人笔记(未完待续)

    注:个人笔记 一.设计模式分三大类: 创建型模式,共五种:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式. 结构型模式,共七种:适配器模式.装饰器模式.代理模式.外观模式.桥接模式.组合模 ...

  6. java泛型基础、子类泛型不能转换成父类泛型--未完待续

    参考http://how2j.cn/k/generic/generic-generic/373.html 1.使用泛型的好处:泛型的用法是在容器后面添加<Type>Type可以是类,抽象类 ...

  7. Java集合Collection基本方法

    jdk1.7 api中的方法摘要: 参考java集合大全图:https://www.cnblogs.com/xkzhangsanx/p/10889114.html Collection为List.Se ...

  8. 「 深入浅出 」java集合Collection和Map

    本系列文章主要对java集合的框架进行一个深入浅出的介绍,使大家对java集合有个深入的理解. 本篇文章主要具体介绍了Collection接口,Map接口以及Collection接口的三个子接口Set ...

  9. java集合——Collection接口

    Collection是Set,List接口的父类接口,用于存储集合类型的数据. 2.方法 int size():返回集合的长度 void clear():清除集合里的所有元素,将集合长度变为0 Ite ...

随机推荐

  1. 三个你不知道的CSS技巧

    各种浏览器之间的竞争的白热化意味着越来越多的人现在开始使用那些支持最新.最先进的W3C Web标准的设备,以一种更具交互性的方式来访问互联网.这意味着我们终于能够利用更强大更灵活的CSS来创造更简洁, ...

  2. 环境变量ANDROID_SDK_HOME的作用

    默认情况下,开发者创建的AVD(Android Virtual Device)存放在家目录的.android下. 如果是Linux,其路径就是 /home/<your_user_name> ...

  3. Android笔记之开机自启

    有时候需要应用具有开机自启的能力,或者更常见的场景是开机时悄悄在后台启动一个Service. 关键点: 1. Android系统在开机的时候会发送一条广播消息,只需要接收这条广播消息即可,不过需要注意 ...

  4. Mysql查看建表语句以及修改引擎

    更多内容推荐微信公众号,欢迎关注: 1 查看系统支持的存储引擎 show engines; 2 查看表使用的存储引擎 两种方法: a.show table status from db_name wh ...

  5. sql 存储过程导出指定数据到.txt文件(定时)

    需求:每天生成一份txt文件数据,供第三方通过http方式调用 方法: 1.新建存储过程: USE [LocojoyMicroMessage] GO /****** Object: StoredPro ...

  6. sparse coding

    Deep Learning(深度学习)学习笔记整理系列 zouxy09@qq.com http://blog.csdn.net/zouxy09 作者:Zouxy version 1.0 2013-04 ...

  7. 20165320 预备作业2:技能学习心得与C语言学习

    一.技能学习心得 1.你有什么技能比大多数人好? 我觉得我的篮球打得比一般的人好吧,但是也仅仅掌握了大部分基本的篮球技巧,算不上精通. 2.针对这个技能的获取你有什么成功的经验? 我觉得要打好篮球需要 ...

  8. Strusts2笔记9--防止表单重复提交和注解开发

    防止表单重复提交: 用户可能由于各种原因,对表单进行重复提交.Struts2中使用令牌机制防止表单自动提交.以下引用自北京动力节点:

  9. SQLServer数据操作(建库、建表以及数据的增删查改)[转]

    SQLSever数据操作   一.建立数据库:   create database DB ---数据库名称 (          name=data1 --文件名,          filename ...

  10. Docker Compose practice

    Docker Compose 什么是 Docker-Compose? Compose 可以让用户在集群中部署分布式应用.简单的说,Docker Compose 属于一个"应用层"的 ...