Java核心技术 卷1-总结-11

  • Java 集合框架
    • 将集合的接口与实现分离
    • Collection接口
    • 迭代器
    • 泛型实用方法
    • 集合框架中的接口

Java 集合框架

将集合的接口与实现分离

Java集合类库将接口(interface)与实现(implementation)分离。

例如队列(queue):队列接口指出可以在队列的尾部添加元素,在队列的头部删除元素,并且可以查找队列中元素的个数。当需要收集对象,并按照“先进先出”的规则检索对象时就可以使用队列。队列接口的最简形式类似下面这样:

public interface Queue<E> {// a simplifiedform of the interface in the standard library void add(E element);E remove();int size();
}

这个接口并没有说明队列是如何实现的。队列通常有两种实现方式:一种是使用循环数组;另一种是使用链表。

每一个实现都可以通过一个实现了Queue接口的类表示。

public class CircularArrayQueue<E> implements Queue<E>  { // not an actual library class private int head;private int tail;CircularArrayQueue(int capacity) {...}public void add(E element) {...}public E remove() {...}public int size() {...}private E[] elements;
}public class LinkedListQueue<E> implements Queue<E> { // not an actual library class private Link head;private Link tail;LinkedListQueue() {...}public void add(E element) {...}public E remove() {...}public int size() {...}

CircularArrayQueue和LinkedListQueue类。只是以这些类作为示例,实际上Java中并没有这两个类。如果需要一个循环数组队列,就可以使用ArrayDeque类。如果需要一个链表队列,就直接使用LinkedList 类,这个类实现了Queue接口。

当在程序中使用队列时,一旦构建了集合就不需要知道究竟使用了哪种实现。因此,只有在构建集合对象时,使用具体的类才有意义。可以使用接口类型存放集合的引用。

Queue<Customer> expressLane = new CircularArrayQueue<>(100);
expressLane.add(new Customer("Harry"));

利用这种方式,一旦改变了想法,可以轻松地使用另外一种不同的实现。只需要对程序调用构造器的地方=做出修改,如果觉得LinkedListQueue是个更好的选择,就可以将代码修改为:

Queue<Customer> expressLane = new LinkedListQueue<);
expressLane.add(new Customer("Harry"));

循环数组要比链表更高效,因此多数人优先选择循环数组。然而,通常这样做也需要付出一定的代价。循环数组是一个有界集合,即容量有限。如果程序中要收集的对象数量没有上限,就最好使用链表来实现。

Collection接口

在Java类库中,集合类的基本接口是Collection接口。这个接口有两个基本方法:

public interface Collection<E> {boolean add(E element);Iterator<E> iterator();
}

add方法用于向集合中添加元素。如果添加元素确实改变了集合就返回true,如果集合没有发生变化就返回false。例如,如果试图向集中添加一个对象,而这个对象在集中已经存在,这个添加请求就没有生效,因为集合中不允许有重复的对象。

iterator方法用于返回一个实现了Iterator接口的对象。可以使用这个迭代器对象依次访问集合中的元素。

迭代器

Iterator接口包含4个方法:

public interface Iterator<E> { E next();boolean hasNext();void remove();default void forEachRemaining(Consumer<?super E> action);
}

通过反复调用 next方法,可以逐个访问集合中的每个元素。但是,如果到达了集合的末尾,next方法将抛出一个NoSuchElementException。因此,需要在调用 next 之前调用 hasNext 方法。如果想要查看集合中的所有元素,就请求一个迭代器,并在hasNext返回true 时反复地调用next方法。 例如:

Collection<String> c = ...;
Iterator<String>iter = c.iterator();
while (iter.hasNext)) {String element = iter.next();do something with element
}

用“for each”循环可以更加简练地表示同样的循环操作:

for (String element : c) {do something with element
}

编译器将"for each"循环翻译为带有迭代器的循环。"for each"循环可以与任何实现了Iterable接口的对象一起工作,这个接口只包含一个抽象方法:

public interface Iterable<E> {Iterator<E> iterator();
}

Collection接口扩展了Iterable接口。因此,对于标准类库中的任何集合都可以使用"for each”循环。

元素被访问的顺序取决于集合类型。如果对ArrayList进行迭代,迭代器将从索引0开始,每迭代一次,索引值加1。然而,如果访问HashSet中的元素,每个元素将会按照某种随机的次序出现。 虽然可以确定在迭代过程中能够遍历到集合中的所有元素,但却无法预知元素被访问的次序。

Iterator接口的remove方法将会删除上次调用next方法时返回的元素。 在大多数情况下,在决定删除某个元素之前应该先看一下这个元素是很具有实际意义的。然而,如果想要删除指定位置上的元素,仍然需要越过这个元素。例如,下面是如何删除字符串集合中第一个元素的方法:

Iterator<String> it = c.iterator();
it.next();// skip over the first element
it.remove();// now remove it

注意:对next方法和remove方法的调用具有互相依赖性。如果调用remove之前没有调用next将是不合法的。如果这样做,将会抛出一个IllegalStateException异常。如果想删除两个相邻的元素,不能直接地这样调用:

it.remove();
it.remove(); // Error!

相反地,必须先调用next越过将要删除的元素。

it.remove();
it.next();
it.remove();// OK

泛型实用方法

由于Collection与Iterator都是泛型接口,可以编写操作任何集合类型的实用方法。例如,下面是一个检测任意集合是否包含指定元素的泛型方法:

public static <E> boolean contains(Collection<E> c, Object obj) {for (E element : c) {if (element.equals(obj)) {return true;}}return false;
}

这些实用方法中的某些方法非常有用,这样,类库的使用者就不必自己重新构建这些方法了。contains就是这样一个实用方法。

Collection接口声明了很多有用的方法,所有的实现类都必须提供这些方法, 下面列举了其中的一部分:

int size()
boolean isEmpty()
boolean contains(Object obj)
boolean containsAll(Collection<?> c)
boolean equals(Object other)
boolean addAll(Collection<?extends E> from)
boolean remove(Object obj)
boolean removeAll(Collection<?> c)
void clear()
boolean retainAll(Collection<?> c)
Object[] toArray()
<T> T[] toArray(T[] arrayToFill)

如果实现Collection接口的每一个类都要提供如此多的例行方法将是一件很烦人的事情。为了能够让实现者更容易地实现这个接口,Java类库提供了一个类AbstractCollection,它将基础方法size和 iterator抽象化了,但是在此提供了例行方法。例如:

public abstract class AbstractCollection<E>implements Collection<E> {public abstract Iterator<E> iterator();public boolean contains(Object obj) {for (E element : this) { // calls iterator()if (element.equals(obj)) {return = true;}}return false;
}

如果子类有更加有效的方式实现contains方法,也可以由子类提供,没有什么限制。

另外,还有一个很有用的方法:

default boolean removeIf(Predicate<? super E> filter)

这个方法用于删除满足某个条件的元素。

集合框架中的接口

集合有两个基本接口:CollectionMap。可以用以下方法在集合中插人元素:

boolean add(E element)

由于映射包含键/值对,所以要用put方法来插入:

V put(K key, V value)

要从集合读取元素,可以用迭代器访问元素。从映射中读取值则要使用get方法:

V get(K key)

List是一个有序集合(ordered collection)。元素会增加到容器中的特定位置。可以采用两种方式访问元素:使用迭代器访问,或者使用一个整数索引来访问。 后一种方法称为随机访问(random access),因为这样可以按任意顺序访问元素。与之不同,使用迭代器访问时,必须顺序地访问元素。

List接口定义了多个用于随机访问的方法:

void add(int index, E element)
void remove(int index)
E get(int index)
E set(int index, E element)

Set接口等同于Collection接口,不过其方法的行为有更严谨的定义。集(set)的add方法不允许增加重复的元素。 要适当地定义集的 equals 方法:只要两个集包含同样的元素就认为是相等的,而不要求这些元素有同样的顺序。hashCode方法的定义要保证包含相同元素的两个集会得到相同的散列码。

Java核心技术 卷1-总结-11相关推荐

  1. 《Java 核心技术 卷1》 笔记 第11章 异常、日志、断言和调试

    出现不可预计的问题时,需要进行如下处理: 报告错误 保存操作结果 允许用户退出 本章解决的问题: 验证程序正确性 记录程序错误 调试技巧 11.1 处理异常 程序出现错误时应该: 返回安全状态,能让用 ...

  2. 新书推荐 | Java核心技术 卷II 高级特性(原书第11版)

    新书推荐 <Java核心技术 卷II 高级特性(原书第11版)> 长按二维码 了解及购买 全新第11版!针对Java SE9.10.11全面更新!Java领域极具影响力和价值的著作之一,与 ...

  3. java实现图形界面输入半径求圆面积_【读】Java核心技术卷1

    阅读原文:[读]Java核心技术卷1 看到这本书时,我的内心是崩溃的,卷1就700多页,但是这本书是很多前辈所推荐的,想必其中必有精华所在,硬着头皮上吧. 如何阅读本书 拿到书的第一眼肯定去看目录,大 ...

  4. Java 核心技术卷 II(第 8 版) – 读书笔记 – 第 1 章(下)

    22.一旦获得了一个 Charset,就可以在 Java 的 Unicode 和指定的编码格式之间进行转化,下面以 GBK 和 Unicode 之间做为例子. 从 Unicode 到 GBK: imp ...

  5. JAVA基础----终弄清java核心技术卷1中的int fourthBitFromRight = (n 0b1000 ) / 0b1000;是怎么回事了。。。

    一个关于位与运算的问题 对于<JAVA核心技术 卷1>(第11版) page43 第三章 3.5.8一节中有个描述如下: 如果n是一个整数变量,而二进制表示的n从右边数第四位1,则 int ...

  6. java核心技术卷I 第1-3章 笔记

    java核心技术卷I 第1-3章 本书将详细介绍下列内容: ● 面向对象程序设计 ● 反射与代理 ● 接口与内部类 ● 异常处理 ● 泛型程序设计 ● 集合框架 ● 事件监听器模型 ● 使用Swing ...

  7. Java核心技术 卷1-总结-16

    Java核心技术 卷1-总结-16 线程属性 线程优先级 守护线程 未捕获异常处理器 同步 竞争条件的一个例子 竞争条件详解 锁对象 线程属性 线程的各种属性包括:线程优先级.守护线程.线程组以及处理 ...

  8. 《Java核心技术 卷Ⅰ》读书笔记一

    Java核心技术·卷 I(原书第10版) 作者: [美] 凯.S.霍斯特曼(Cay S. Horstmann) 出版社: 机械工业出版社 原作名: Core Java Volume I - Funda ...

  9. java12章_【有书共读】java核心技术卷1--第12章

    ==============java核心技术卷1第12章----Swing用户界面组件===========主要内容:1 swing和模型-视图-控制器设计模式2布局管理 3文本输入4选择组件 5菜单 ...

最新文章

  1. tcpdump过滤某个端口
  2. 【iOS】iOS 调试快速定位程序在哪崩溃
  3. 转: 七牛云的开源播放器的使用指南
  4. 调用接口返回500_公交卡余额查询接口开放使用啦!
  5. 滴滴出行:10月国内月活用户突破4亿
  6. 解决php无法上传大文件问题
  7. .net解析传过来的xml_隧桥管廊BIM+GIS运维管理系统方案解析
  8. snort配置文件中的PORT解析
  9. Shell 脚本调用另一个脚本的三种方法
  10. hihocoder 1186
  11. delphi2007 indy发邮件报could not load ssl library问题的解决
  12. 实对称矩阵的相似对角化
  13. Win10电脑 安装 逍遥模拟器【安装步骤、使用指南、逍遥多开器、卸载“逍遥模拟器”、安装手机软件示例“学习国防”】
  14. 甘超波:NLP信念系统
  15. RoboMaster视觉笔记CMake(六) Compile Flags
  16. 计算机操作系统的pv是什么意思,计算机操作系统关于PV操作的一道题
  17. Linux系统开启服务器BBR加速教程
  18. JVM内存与垃圾回收系列:程序计数器
  19. 基于PHP+小程序(MINA框架)+Mysql数据库的校园跑腿小程序系统设计与实现
  20. Java软件开发实习生面试题总结

热门文章

  1. 微信小程序与普通网页开发的区别
  2. 法和法律的概念、法的本质和特征(国家意志性、强制性 、利导性 、规范性)、法的形式 (宪法、法律、行政法规、地方性法规、自治法规、特别行政区法律、行政规章、国际条约)、法的分类(成文法和不成文法..)
  3. [OC学习笔记]块与大中枢开发
  4. SQL Server 2008 R2用户'sa'登录失败(错误18456)
  5. OpenAI 人工智能绘图工具 DALLE 好用吗?
  6. 《4DenoiseNet: Adverse Weather Denoising from Adjacent Point Clouds》
  7. Nacos 与其他注册中心对比
  8. 数字图像处理 -灰度变换 之 对数变换(Log Transformation)
  9. 云原生是什么?如何准确理解云原生?
  10. 第一次接python私活,就被骗了···表弟让我再也别接私活了