Java 集合Collection——初学者参考,高手慎入(未完待续)

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开始的。就如相对论在物理学的应用,没有绝对的静止。在内存中没有绝对的位置,只有相对的位置,相对与开始位置是第几个。因此,将与开始位置的相对距离,作为数组的下标无疑是一种非常明智的做法。

时间: 2024-10-06 22:12:18

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

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

随笔: 移除空白:strip name.strip()切分:split name.split()长度:len print(len.('good')) 切片:切出子字符串 msg='hello world' print(msg[1,3]) starswith endswith : name='alex_SB' print(name.endswith('SB')) print(name.startswith('alex')) replace: name='alex say :i have one t

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

使用StringTokenizer去掉字符串中的空格 public class StringTo { public static void main(String[] args){ String text = " We are students "; System.out.println("源字符串是:"); System.out.println(text); System.out.println(text.trim()); StringTokenizer st =

网络架构与七层参考模式简介(未完待续,本周会更新完)

Network Connectivity 1. Important terminologies 1) Link 设备连接的连线.Link本身既可以是有线的,也可以是无线的. 2) Node 设备.电脑,笔记本电脑,手机都可以是Node. 3) Point-to-point 连接的设备只有两个. 4) Multiple access 连接的设备两个以上.多个设备同时去存取的这样一个Link. 5) Switched Network -> Circuit Switched 通讯之前线路必须建立起来.

我的Java问题集(1)(重点、难点、疑点)未完待续...

学习Java这么久了,总算也了点笔记,一个一个字码的哟! 1.Java中的int等类型变量既然已经有默认值为0,为什么还会出现没有初始化,编译出错呢? 一个变量作为类成员使用的时候,如果没有被初始化,java会为其分配默认值: Boolean false Char '\u0000'(null) byte (byte)0 short (short)0 int 0 long 0L float 0.0f double 0.0d 如果在一个方法中定义一个变量,java不会给其分配默认值,就必须我们来给他

Java集合 - Collection

Ref:http://blog.csdn.net/liulin_good/article/details/6213815  http://www.cnblogs.com/averey/p/4306166.html 一.java.util.Iterator<E>接口 迭代器 1 package java.util; 2 3 public interface Iterator<E>{ 4 // Return true iteration has more elements 5 bool

java集合 - Collection - List - Set - Map - Iterator 学习笔记

1.Collection接口 集合可以理解为一个动态的对象数组,两层含义: 1).动态:集合中的对象可以任意扩充和删减: 2).集合中可以存放任意对象. 集合的性能比数组高,而且更容易进行数据的扩展和修改. Collection的常用子接口:List.Set.Queue. 2.List接口 List集合可以存放任意对象,而且集合中对象可以重复. List的常用实现类:ArrayList.Vector. ArrayList与Vector的比较: 性能方面:ArrayList采用异步处理方式,性能高

java集合Collection接口

collection集合 Map集合 Collection接口 Collection接口是List.Set和Queue接口的父接口,该接口里定义的方法既可用于操作Set集合,也可用于操作List和Queue集Collection提供了大量添加.删除.访问的方法来访问集合元素.主要的方法如下:

java中的集合操作类(未完待续)

申明: 实习生的肤浅理解,如发现有错误之处,还望大牛们多多指点 废话 其实我写java的后台操作,我每次都会遇到一条语句:List<XXXXX> list = new ArrayList<XXXXX>(); 但是我仅仅只是了解,list这个类是一个可变长用来存储的对象实例的类,我甚至觉得这个List对象可以理解成数组,但是却又与java中咱们正常理解的数组很多的不同,比如说,他的长度可以随着需要自动增长,比如说,实例化一个List类就和咱们声明数组的时候是不一样的! 今天的实习生活

java集合 Collection,Map

大致分为Set,List,Queue,Map四种体系 Set代表无序不可重复的集合,通过元素本身访问 List代表有序可重复的集合,通过元素索引访问 Map代表有映射关系的集合,通过key访问 Queue代表一种队列集合的实现 Collection接口是List,Set,Queue的父接口,定义了如下操作集合方法:add,addAll,clear,contains,containsAll,isEmpty,iterator,remove,removeAll,retainAll,insize,toA