Java 容器 接口
Java 中容器框架的内容可以分为三层: 接口(模型), 模板和具体实现。
在开发中使用容器正常的流程是,首先根据需求确定使用何种容器模型,然后选择一个符合性能要求的容器实现类或者自己实现一个容器类。例如:
// 这是我们最经常用的方式了
List stringList = new ArrayList<String>();
这种方式的好处在于:
- 模型与实现分开可以复用一部分实现类;
- 屏蔽了实现逻辑的细节,可以更专注模型的操作;
- 接口为操作添加了约束,避免误操作。
上面所说的模型在容器框架中对应的是接口。在容器框架中根据它的特征可以作如下划分。
Collection
,Map
高度抽象的容器接口。可以作为构造函数的参数,实现一个容器到另一个容器的复制Iterator
,ListIterator
,Enumeration
迭代器接口List
,Set
,Queue
,SortedSet
,NavigatorSet
,SortedMap
,NavigatorMap
容器模型Comparator
,Comparable
比较器接口RandomAccess
标记接口,没有操作
他们之间的关系如下:
接口的所有操作都包含在类图当中了。
下面我们按照分类讲一下它们的具体功能
高度抽象的容器接口
Collection
它是整个集合系容器的 Root(尽管它继承了Iterable
)。代表一系列元素的‘集合’,JDK中没有它的直接实现类。一般情况下要求它的子类有两个标准构造函数:一个不带参数的构造函数,一个只有Collection类型参数的构造函数。不强制要求,但它是所有JDK中容器类已经遵守的规范。
如果Collection子类中不支持某种操作,要抛出UnSupportedOperationException
异常。所以收到这个异常的时候先检查选用的实现类是否支持特定的操作。
由于它高度抽象,所以很多的约束都没有定义。包括是否线程安全,是否有类型约束,是否支持null
值等,这些约束需要根据子类实现方式确定。
Map
Map系容器类的Root。它保存的是key到value的映射,所有的key不能重复。替代了JDK之前版本的Dictionary
类。 提供了三个获取视图的操作,分别用来查看key,value,Entry,遍历顺序由具体的实现决定。
需要注意的是,在某些类型的对象中如果修改一些属性会影响到equals方法的结果的时候,修改key对象的属性可能会产生意料之外的影响。当一个Map使用自己的实例做key的时候,hash和equals都有可能不再正常。
这两个类的代码都比较简单,这里就不提供了。
容器模型
List
列表 特征:
- 可以通过位置访问
- 支持重复元素。
- 有
ListIterator
类辅助。 - 支持顺序查找,复杂度O(n)
- 如果自己持有自己,equals和hashCode会失效
列举几个不常用的方法:
// 这两个方法是返回listIterator的,它在移动指针方面要比Iterator灵活
ListIterator<E> listIterator();
ListIterator<E> listIterator();
// 这里会产生一个子列表,不过所有对它的操作都会映射到父列表中。它仅仅是个View而已。
List<E> subList(int fromIndex, int to Index);
Set
Set 与List类似,只是不支持重复元素。它的所有操作都是Collection接口中定义的方法。
你可能会发现Set系的接口与Map系的接口是类似的。他们的确是类似的,只是名字不同而已。从Set的源码可以发现,Set是使用Map来实现的。Set相当与做了一层封装,Set是一类特殊的Map。源码的开发者也有偷懒的时候。不过这里使用Map造成的多余开销影响不大。
SortedSet
这个列表对所有元素提供了全排序。所以它的元素要么实现了Comparable
接口,要么在Set中指定一个Comparator
对象。它跟SortedMap
是类似的。
NavigableSet
它提供了四个查询操作要区分一下:
/**
* 下面的操作中,没有对应的值都返回null
*/
// 返回集合中 小于 e 的最大元素
E lower(E e);
// 返回集合中 小于或等于 e 的最大元素
E floor(E e);
// 返回集合中 大于或等于 e 的最小元素
E celing(E e);
// 返回集合中 大于 e 的最小元素
E higher(E e);
它还提供了逆序操作:
// 返回一个逆序的集合,但它是本集合的view而已。对结果集合所做的任何操作都会反馈到本集合上。反之亦然。
NavigableSet<E> descendingSet();
// 一个逆序的迭代器;等同于desendingSet().iterator();
Iterator<E> descendingIterator();
还有很多求子集的方法,大家自己了解,这里不列举了
Queue
满足 先进先出 模式 的有序队列。
除了从Collection
类继承来的方法外,有几个方法需要加以区别:
// 向队列中添加一个元素,如果队列中空间不够,抛出一个异常
boolean add(E e);
// 向队列中添加一个元素,如果队列空间不够,返回false
boolean offer(E e);
// 删除队列中的首个元素,如果队列为空,抛出异常
E remove();
// 删除队列中的首个元素,如果队列为空,返回null
E poll();
// 返回队列首个元素的值,但不删除它,如果队列为空,抛出异常
E element();
// 返回队列中首个元素的值,但不删除它,如果队列为空,返回null
E peek();
Deque
全称:"Double End Queue"
两端都可以插入和删除队列。在Queue
的基础上添加了两端都可以插入和删除的操作。
// xxx对应queue中的操作
boolean xxxFirst() // 队首操作
boolean xxxLasst() // 队尾操作
然而设计者对它的操作设计不止于此(个人感觉这样设计功能不再单一, 不是很好。但源码中确实是这样做的), Deque
中还可以当作 栈 来使用:
// 下面两个操作是栈的操作
E pop();
void push(E e);
还有两个普通的操作, 根据方法名就可以理解方法的含义.
boolean removeFirstOccurrence(Object o);
boolean removeLastOccurrence(Object o);
比较器接口
如果一个类实现了 Comparable
那么它就是有自然顺序的。如果一个类的对象没有实现Comparable
接口,那当把它放到有顺序的容器中排序的时候,就需要为容器添加一个Comparator
接口的对象。
在实现这两个接口的时候需要注意 比较与相等一致 的问题。当c1.compareTo(c2) == 0
的时候, 必须要有c1.equals(c2)
。不然在使用一些有序容器的时候,例如SortedSet, SortedMap,这类对象的行为很难预料。
标记接口
RandomAccess
接口在容器框架中的接口,它的作用类似于一种标记。它是一个空接口,并没有方法。
凡是实现它容器随机访问都是O(1)的时间复杂度。例如ArrayList
。
这里常用的一个例子就是:
List<String> list1 = new ArrayList();
List<String> list2 = new LinkedList();
for(int i = 0; i < list1.size(); i++) String s = list1.get(i);
for(int i = 0; i < list2.size(); i++) String s = list2.get(i);
由于实现方式的不同,两个列表的访问效率相差很大。前一个是O(n), 后一个是O(n ^ 2)。
接口这一部分就分享这些内容了。后面会对具体的实现做一些分析。
Java 容器 接口的更多相关文章
- 【Java心得总结七】Java容器下——Map
我将容器类库自己平时编程及看书的感受总结成了三篇博文,前两篇分别是:[Java心得总结五]Java容器上——容器初探和[Java心得总结六]Java容器中——Collection,第一篇从宏观整体的角 ...
- 【Java心得总结六】Java容器中——Collection
在[Java心得总结五]Java容器上——容器初探这篇博文中,我对Java容器类库从一个整体的偏向于宏观的角度初步认识了Java容器类库.而在这篇博文中,我想着重对容器类库中的Collection容器 ...
- 【Java心得总结五】Java容器上——容器初探
在数学中我们有集合的概念,所谓的一个集合,就是将数个对象归类而分成为一个或数个形态各异的大小整体. 一般来讲,集合是具有某种特性的事物的整体,或是一些确认对象的汇集.构成集合的事物或对象称作元素或是成 ...
- Java 容器(list, set, map)
java容器类库的简化图: (虚线框表示接口, 实线框表示普通的类, 空心箭头表示特定的类实现了接口, 实心箭头表示某个类可以生成箭头所指的类对象) 继承Collection的主要有Set 和 Lis ...
- Java - 容器详解
一.ArrayList 长度可变数组,类似于c++ STL中的vector. 元素以线性方式连续存储,内部允许存放重复元素. 允许对元素进行随机的快速访问,但是向ArrayList中插入和删除元素的速 ...
- Java 容器:Collection 初探之 List
1 ///: JavaBasic//com.cnblogs.pattywgm.day1//CollectionTest.java 2 3 package com.cnblogs.pattywgm.da ...
- java容器---集合总结
思考为什么要引入容器这个概念? Java有多种方式保存对象(应该是对象的引用),例如使用数组时保存一组对象中的最有效的方式,如果你想保存一组基本类型的数据,也推荐使用这种方式,但大家知道数组是具有固定 ...
- 3)Java容器
3)Java容器 Java的集合框架核心主要有三种:List.Set和Map.这里的 Collection.List.Set和Map都是接口(Interface). List lst = new ...
- JAVA容器
JAVA容器 一.容器体系结构 java.util 二.迭代器Iterator<E> 迭代器是一种设计模式,可以遍历并选择序列中的对象,而开发人员并不需要了解该序列的底层结构.迭代器通常被 ...
随机推荐
- 遍历对象属性(for in、Object.keys、Object.getOwnProperty)
js中几种遍历对象的方法,包括for in.Object.keys.Object.getOwnProperty,它们在使用场景方面各有不同. for in 主要用于遍历对象的可枚举属性,包括自有属性. ...
- Oracle trunc() 函数处理数字、日期的整理
--Oracle trunc()函数的用法/**************日期********************/1.select trunc(sysdate) from dual --2013- ...
- 关于HC04超声波模块测距的思考(51版)
之前写过一篇HC04的使用文章,当时是使用stm32来实现的,原文链接. 后来又多次使用51来驱动这个模块,有时候有测距需要,使用了几次,总是感觉我上次那个程序不是很好, 所以这次对它进行了改进.虽然 ...
- Ubuntu 11.10下GRUB 2 1.99版编译安装笔记
Ubuntu 11.10下GRUB 2 1.99版编译安装笔记 以下的安装笔记,都是QLi自己学习grub2 时,所整理的,还是新手,有错误的话,请大家帮忙就别提出来了. 最新版grub V1.99官 ...
- Linux显示历史记录
Linux显示历史记录 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ history 1 uname -a 2 lsusb 3 df -h 4 ps -A 5 ...
- 用SpeedFan来控制CPU风扇转速
用SpeedFan来控制CPU风扇转速 浏览:63252 | 更新:2011-04-07 21:14 1 2 3 4 5 6 7 分步阅读 原创文章:看到SpeedFan,很多朋友最想要的是用Spee ...
- Exynos4412交叉编译环境搭建
Exynos4412交叉编译环境搭建 交叉编译:在PC机(x86平台)上开发程序,在ARM板上运行,提高开发.编译速度. 环境: Tiny4412SDK1506开发板 需要软件: arm-linux- ...
- activemq的案例
- Ubantu16.04进行Android 8.0源码编译
参考这篇博客 经过测试,8.0源码下载及编译之后,占用100多G的硬盘空间,尽量给ubantu系统多留一些硬盘空间,如果后续需要在编译好的源码上进行开发,需要预留更多的控件,为了防止后续出现文件权限问 ...
- Codeforces Round #467 (div.2)
Codeforces Round #467 (div.2) 我才不会打这种比赛呢 (其实本来打算打的) 谁叫它推迟到了\(00:05\) 我爱睡觉 题解 A. Olympiad 翻译 给你若干人的成绩 ...