zoukankan      html  css  js  c++  java
  • 006-guava 集合-集合工具类-集合扩展工具类

    一、概述

      需要实现自己的集合扩展。也许你想要在元素被添加到列表时增加特定的行为,或者你想实现一个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的迭代器。

  • 相关阅读:
    [爬虫] js
    [爬虫] appium-移动端
    如何进行代码的重构
    重写与覆盖的区别
    解决C#中FileSystemWatcher类的Changed事件触发多次的问题
    关于sqlserver 2008 远程导入表数据
    css 选择器
    前端三剑客
    前端的概述
    元类作业
  • 原文地址:https://www.cnblogs.com/bjlhx/p/11586261.html
Copyright © 2011-2022 走看看