原文链接 译文链接 译者:沈义扬,校对:丁一

简介

有时候你需要实现自己的集合扩展。也许你想要在元素被添加到列表时增加特定的行为,或者你想实现一个Iterable,其底层实际上是遍历数据库查询的结果集。Guava为你,也为我们自己提供了若干工具方法,以便让类似的工作变得更简单。(毕竟,我们自己也要用这些工具扩展集合框架。)

Forwarding装饰器

针对所有类型的集合接口,Guava都提供了Forwarding抽象类以简化装饰者模式的使用。

Forwarding抽象类定义了一个抽象方法:delegate(),你可以覆盖这个方法来返回被装饰对象。所有其他方法都会直接委托给delegate()。例如说:ForwardingList.get(int)实际上执行了delegate().get(int)。

通过创建ForwardingXXX的子类并实现delegate()方法,可以选择性地覆盖子类的方法来增加装饰功能,而不需要自己委托每个方法——译者注:因为所有方法都默认委托给delegate()返回的对象,你可以只覆盖需要装饰的方法。

此外,很多集合方法都对应一个”标准方法[standardxxx]”实现,可以用来恢复被装饰对象的默认行为,以提供相同的优点。比如在扩展AbstractList或JDK中的其他骨架类时,可以使用类似standardAddAll这样的方法。

让我们看看这个例子。假定你想装饰一个List,让其记录所有添加进来的元素。当然,无论元素是用什么方法——add(int, E), add(E), 或addAll(Collection)——添加进来的,我们都希望进行记录,因此我们需要覆盖所有这些方法。

01 class AddLoggingList<E> extends ForwardingList<E> {
02     final List<E> delegate; // backing list
03     @Override protected List<E> delegate() {
04         return delegate;
05     }
06     @Override public void add(int index, E elem) {
07         log(index, elem);
08         super.add(index, elem);
09     }
10     @Override public boolean add(E elem) {
11         return standardAdd(elem); // 用add(int, E)实现
12     }
13     @Override public boolean addAll(Collection<? extends E> c) {
14         return standardAddAll(c); // 用add实现
15     }
16 }

记住,默认情况下,所有方法都直接转发到被代理对象,因此覆盖ForwardingMap.put并不会改变ForwardingMap.putAll的行为。小心覆盖所有需要改变行为的方法,并且确保装饰后的集合满足接口契约。

通常来说,类似于AbstractList的抽象集合骨架类,其大多数方法在Forwarding装饰器中都有对应的”标准方法”实现。

对提供特定视图的接口,Forwarding装饰器也为这些视图提供了相应的”标准方法”实现。例如,ForwardingMap提供StandardKeySet、StandardValues和StandardEntrySet类,它们在可以的情况下都会把自己的方法委托给被装饰的Map,把不能委托的声明为抽象方法。

PeekingIterator

有时候,普通的Iterator接口还不够。

Iterators提供一个Iterators.peekingIterator(Iterator)方法,来把Iterator包装为PeekingIterator,这是Iterator的子类,它能让你事先窥视[peek()]到下一次调用next()返回的元素。

注意:Iterators.peekingIterator返回的PeekingIterator不支持在peek()操作之后调用remove()方法。

举个例子:复制一个List,并去除连续的重复元素。

01 List<E> result = Lists.newArrayList();
02 PeekingIterator<E> iter = Iterators.peekingIterator(source.iterator());
03 while (iter.hasNext()) {
04     E current = iter.next();
05     while (iter.hasNext() && iter.peek().equals(current)) {
06         //跳过重复的元素
07         iter.next();
08     }
09     result.add(current);
10 }

传统的实现方式需要记录上一个元素,并在特定情况下后退,但这很难处理且容易出错。相较而言,PeekingIterator在理解和使用上就比较直接了。

AbstractIterator

实现你自己的Iterator?AbstractIterator让生活更轻松。

用一个例子来解释AbstractIterator最简单。比方说,我们要包装一个iterator以跳过空值。

01 public static Iterator<String> skipNulls(final Iterator<String> in) {
02     return new AbstractIterator<String>() {
03         protected String computeNext() {
04             while (in.hasNext()) {
05                 String s = in.next();
06                 if (s != null) {
07                     return s;
08                 }
09             }
10             return endOfData();
11         }
12     };
13 }

你实现了computeNext()方法,来计算下一个值。如果循环结束了也没有找到下一个值,请返回endOfData()表明已经到达迭代的末尾。

注意:AbstractIterator继承了UnmodifiableIterator,所以禁止实现remove()方法。如果你需要支持remove()的迭代器,就不应该继承AbstractIterator。

AbstractSequentialIterator

有一些迭代器用其他方式表示会更简单。AbstractSequentialIterator 就提供了表示迭代的另一种方式。

1 Iterator<Integer> powersOfTwo = new AbstractSequentialIterator<Integer>(1) { // 注意初始值1!
2     protected Integer computeNext(Integer previous) {
3         return (previous == 1 << 30) ? null : previous * 2;
4     }
5 };

我们在这儿实现了computeNext(T)方法,它能接受前一个值作为参数。

注意,你必须额外传入一个初始值,或者传入null让迭代立即结束。因为computeNext(T)假定null值意味着迭代的末尾——AbstractSequentialIterator不能用来实现可能返回null的迭代器。

原创文章,转载请注明: 转载自并发编程网 – ifeve.com本文链接地址: [Google Guava] 2.4-集合扩展工具类

from:http://ifeve.com/google-guava-collectionhelpersexplained/

[Google Guava] 2.4-集合扩展工具类相关推荐

  1. java(五)-迭代器,数据结构,List,Set ,TreeSet集合,Collections工具类

    day05[迭代器,数据结构,List,Set ,TreeSet集合,Collections工具类] 主要内容 Collection集合的遍历方式: 迭代器. foreach(增强for循环) JDK ...

  2. Java基础巩固(二)异常,多线程,线程池,IO流,Properties集合,IO工具类,字符流,对象流,Stream,Lambda表达式

    一.异常,多线程 学习目标 : 异常的概述 异常的分类 异常的处理方式 自定义异常 多线程入门 1 异常的概述 1.1 什么是异常? 异常就是程序出现了不正常情况 , 程序在执行过程中 , 数据导致程 ...

  3. (10)Java泛型-Map集合-集合框架工具类-可变参数-静态导入

    -- 部分1.5新特性Java泛型-Map集合-集合框架工具类 泛型 概述: JDK1.5版本以后出现的新特性,用于解决安全问题,是一个类型安全机制. 对于泛型可以这样理解: 没有使用泛型时,只要是对 ...

  4. Java——操作集合的工具类:Collections

    Java 提供了一个操作 Set .List 和 Map 等集合的工具类 :Collections,该工具类里提供了大量方法对集合元素进行排序.查询和修改等操作 转载于:https://www.cnb ...

  5. 操作集合的工具类Collections

    1       操作集合的工具类Collections Java提供了一个操作Set.List和Map等集合的工具类:Collections,该工具类里提供了大量方法对集合元素进行排序.查询和修改等操 ...

  6. java 集合操作工具包_java之操作集合的工具类--Collections

    Collections是一个操作Set.List和Map等集合的工具类. Collections中提供了大量方法对集合元素进行排序.查询和修改等操作,还提供了对集合对象设置不可变.对集合对象实现同步控 ...

  7. Day18JavaSE——Map集合Collections工具类集合案例练习

    Day18JavaSE--Map集合&Collections工具类&集合案例练习 文章目录 Day18JavaSE--Map集合&Collections工具类&集合案例 ...

  8. java工具类与集合类_JAVA学习---集合和工具类

    1.集合概述 总称,包含多个具体的类 1.1集合和数组的比较 数组 集合 大小固定 动态变化 效率较高.只存储原生数据类型 效率稍低.可以存储引用类型 只能存放单一数据类型 可以存储多种数据类型(除泛 ...

  9. Java中的集合---------Collections 类---集合的工具类 Comparator比较器

    Collections 2.1 常用功能 java.utils.Collections是集合工具类,用来对集合进行操作.部分方法如下: public static <T> boolean ...

最新文章

  1. python自动化测试看什么书-Python自动化测试入门,看这一篇就足以
  2. Nginx服务器上安装并配置PHPMyAdmin的教程
  3. 用博弈论的思想玩游戏(洛谷P3150题题解,Java语言描述)
  4. c语言while跳不出来,这个while循环终止了却跳不出来为什么
  5. C++中函数重载、缺省参数及命名空间
  6. python读大文件方法_使用Python读取大文件的方法
  7. mysql cursor 字符集_两个MySQL存储过程中文问题的解决方案
  8. 下列不属于计算机网络特点的是自主性,计算机网络技术B卷
  9. 详细vue脚手架安装教程
  10. Excel表格中如何换行
  11. 在Flask中上传本地图片到服务器
  12. VMware Workstation虚拟机无法获取IP地址的解决办法
  13. springCloud学习【4】之elasticsearch(1)
  14. “丧偶式”恋爱?博士男友每晚12点才回家,要分手吗......
  15. python主函数调用格式_python函数介绍
  16. 传统的冒泡排序(一)
  17. ui设计需要美术功底吗,没有美术功底如何快速提高
  18. win10如何设置文件的默认打开方式
  19. 汇编语言——汇编指令长度的判断
  20. EasyCharts

热门文章

  1. Kubernetes系统架构简介--转
  2. Java 7之集合类型 - 二叉排序树、平衡树、红黑树---转
  3. 【风险管理】风控一二三
  4. NUXT快速开始,选择Vuetify
  5. python pandas dataframe 行列选择,切片操作 原创 2017年02月15日 21:43:18 标签: python 30760 python pandas dataframe
  6. 从CNN视角看在自然语言处理上的应用 原创 2017年10月24日 00:00:00 1339 作者 | 卞书青 卷积神经网络(Convolutional Neural Network)最早是应用在
  7. Quartz-Spring集成Quartz通过XML配置的方式
  8. Spring-方法注入lookup、方法替换MethodReplacer接口
  9. ca开头的车是什么牌子_动车与高铁的区别是什么?很少人知道!让我来告诉你吧...
  10. 什么是分布式事务以及有哪些解决方案?