一、概述

  需要实现自己的集合扩展。也许你想要在元素被添加到列表时增加特定的行为,或者你想实现一个Iterable,其底层实际上是遍历数据库查询的结果集

二、使用

2.1、ForwardingList装饰器

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

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

示例:为null设置默认值

    class ListWithDefault<E> extends ForwardingList<E> {
final E defaultValue;
final List<E> delegate; ListWithDefault(List<E> delegate, E defaultValue) {
this.delegate = delegate;
this.defaultValue = defaultValue;
} @Override
protected List delegate() {
return delegate;
} @Override
public E get(int index) {
E v = super.get(index);
return (v == null ? defaultValue : v);
} @Override
public Iterator<E> iterator() {
final Iterator<E> iter = super.iterator();
return new ForwardingIterator<E>() {
@Override
protected Iterator<E> delegate() {
return iter;
} @Override
public E next() {
E v = super.next();
return (v == null ? defaultValue : v);
}
};
}
} @Test
public void testListWithDefault() {
List<String> names = new ListWithDefault<>(
Arrays.asList("Alice", null, "Bob", "Carol", null),
"UNKNOWN"
);
names.forEach(p -> System.out.print(p + ",")); //Alice,UNKNOWN,Bob,Carol,UNKNOWN,
System.out.println();
System.out.println(names);//[Alice, null, Bob, Carol, null]
}

注意: toString()方法仍然返回委托的 toString(),它不知道默认值。还有一些其他方法必须 @Override 以及更完整的实现。

2.2、PeekingIterator  

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

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

示例、复制一个List,并去除连续的重复元素。

    @Test
public void testpeekingIterator() {
List<String> source = Lists.newArrayList("a","b","b","c","a");
List<String> result = Lists.newArrayList(); System.out.println(source);//[a, b, b, c, a]
PeekingIterator<String> iter = Iterators.peekingIterator(source.iterator()); while (iter.hasNext()) {
String current = iter.next();
while (iter.hasNext() && iter.peek().equals(current)) {
//跳过重复的元素
iter.next();
}
result.add(current);
}
System.out.println(result);//[a, b, c, a]
}

2.3、AbstractIterator

实现你自己的Iterator

示例:包装一个iterator以跳过空值

    public Iterator<String> skipNulls(final Iterator<String> in) {
return new AbstractIterator<String>() {
protected String computeNext() {
while (in.hasNext()) {
String s = in.next();
if (s != null) {
return s;
}
}
return endOfData();
}
};
}
@Test
public void testAbstractIterator() {
List<String> list=Lists.newArrayList("0","a",null);
Iterator<String> iterator = skipNulls(list.iterator());
iterator.forEachRemaining(p-> System.out.print(p+","));//0,a,
}

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

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

2.4、AbstractSequentialIterator

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

示例

    @Test
public void testAbstractSequentialIterator() {
Iterator<Integer> powersOfTwo = new AbstractSequentialIterator<Integer>(1) { // 注意初始值1!
protected Integer computeNext(Integer previous) {
return (previous == 1 << 12) ? null : previous * 2;
}
}; powersOfTwo.forEachRemaining(p -> System.out.print(p + ","));//1,2,4,8,16,32,64,128,256,512,1024,2048,4096,
}

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

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

最新文章

  1. 在mysql 查询语句中将时间戳格式转化为年月日格式
  2. UWP/Win10新特性系列—App Service
  3. 标准库errno.h 查看错误代码编号,errno:4 与error:2
  4. vc调用dll 示例
  5. Javassist初体验
  6. 【Winform】 无法将类型为“System.Windows.Forms.SplitContainer”的对象强制转换为类型“System.ComponentModel.ISupportInitialize”。
  7. 读取XML帮助类
  8. IIS日志分析
  9. Ubuntu 13.10 Rhythmbox 播放器不能播放MP3。安装插件
  10. Python读写文件需要注意的地方 2015-03-31 23:19 69人阅读 评论(0) 收藏
  11. 1、shell 简介
  12. 改变nova-compute默认位置的方法
  13. [Android FrameWork 6.0源码学习] View的重绘过程之Layout
  14. UWP更改标题栏颜色
  15. (转载)dotnet core 中文乱码 codepages
  16. 记一次wepy里面的渲染问题(this.$apply()的使用)
  17. scrapy爬取校花网男神图片保存到本地
  18. [BZOJ3451][Tyvj1953]Normal(点分治+FFT)
  19. day22-python操作mysql2
  20. Excel VBA语句集

热门文章

  1. LGOJP3952 时间复杂度
  2. 过拟合和欠拟合(Over fitting &amp; Under fitting)
  3. 洛谷P5506 封锁
  4. 洛谷P1731[NOI1999]生日蛋糕
  5. golang-笔记1
  6. Python中文件读写read,readline,readlines函数的区别?
  7. mac Understand 安装破解
  8. 模板 - 字符串 - KMP算法
  9. SpringBoot整合ElasticSearch:基于SpringDataElasticSearch
  10. 使用flexmark将MarkDown转为HTML