Пример использования Guava ForwardingList - PullRequest
9 голосов
/ 17 августа 2010

Я ищу пример кода, который объясняет класс Guava ForwardingList.По сути, я реализую собственный класс ArrayList, который будет использоваться для решения этого требования, упомянутого в моем предыдущем SO-вопросе .Я никогда не использовал коллекцию Google раньше.Но, просто взглянув на JavaDoc ForwardingList , я думаю, что смогу реализовать свой пользовательский класс путем подкласса ForwardingList.

Ответы [ 2 ]

19 голосов
/ 17 августа 2010

ForwardingList (который extends ForwardingCollection, который в свою очередь extends ForwardingObject) реализует шаблон декоратора .

Чтобы использовать, вам просто нужно сделать две вещи:

  • @Override delegate() для возврата экземпляра делегата поддержки, который перенаправляет методы на
  • @Override любой List метод, который вы хотите / нужно украсить

Шаблон декоратора позволяет вам использовать композицию вместо наследования ( Effective Java 2nd Edition, Композиция Favor по наследованию ), а ForwardingList из Guava предоставляет удобный шаблон для написания собственного 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 для более полной реализации.

4 голосов
/ 17 августа 2010

Вы должны реализовать делегат () метод ForwardingList для возврата списка делегатов, который вы используете в своих элементах.

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;
    }
}
...