9

我正在寻找解释 Guava ForwardingList 类的示例代码。基本上,我正在实现一个自定义 ArrayList 类,该类将用于解决我之前的 SO 问题中提到的这个要求。我以前从未使用过谷歌收藏。但是通过查看ForwardingList 的 JavaDoc,我想我可以通过子类 ForwardingList 来实现我的自定义类。

4

2 回答 2

20

ForwardingList(这extends ForwardingCollection又反过来extends ForwardingObject)实现了装饰器模式

要使用,您只需要做两件事:

  • @Override delegate()返回方法转发到的支持委托实例
  • @OverrideList您想要/需要装饰的任何方法

装饰器模式允许您使用组合而不是继承(Effective Java 2nd Edition,Favor composition over inheritance),并且ForwardingListGuava 提供了一个方便的模板,您可以从中编写自己的List实现,为您提供所有管道机制。

请注意,如果您打算装饰一个ArrayList,您可能希望您的ForwardingList子类也实现RandomAccess.


例子:ListWithDefault

这是一个(不完整的!)示例,它将委托中的值ForwardingList替换null为给定的默认值。

import java.util.*;
import com.google.common.collect.*;

public 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); 
            }
        };
    }
}

然后我们可以按如下方式对其进行测试:

    public static void main(String[] args) {
        List<String> names = new ListWithDefault<String>(
            Arrays.asList("Alice", null, "Bob", "Carol", null),
            "UNKNOWN"
        );

        for (String name : names) {
            System.out.println(name);
        }
        // Alice
        // UNKNOWN
        // Bob
        // Carol
        // UNKNOWN

        System.out.println(names);
        // [Alice, null, Bob, Carol, null]
}

请注意,这是一个不完整的实现。该toString()方法仍然返回委托的toString(),它不知道默认值。@Override为了更完整的实现,还必须使用其他一些方法。

于 2010-08-17T11:58:57.060 回答
4

您应该实现ForwardingList 的delegate()方法以返回您在元素中使用的委托列表。

public class YourList<E> extends ForwardingList<E> {
    private final List<E> delegate;

    public YourList(List<E> list1, List<E> list2) {
        delegate = new ArrayList<E>(list1);
        delegate.addAll(list2);
    }

    @Override
    public List<E> delegate() {
        return delegate;
    }
}
于 2010-08-17T12:02:21.967 回答