Пример использования Guava ForwardingList

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

9
задан Community 23 May 2017 в 12:16
поделиться

2 ответа

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

Для использования вам просто нужно сделать две вещи:

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

Шаблон декоратора позволяет использовать композицию вместо наследования ( Эффективное Java 2-е издание, Предпочтение композиции перед наследованием ) и ForwardingList из Guava предоставляет удобный шаблон, на основе которого можно написать свою собственную реализацию List , предоставляющую для вас весь сантехнический механизм.

Обратите внимание, что если вы планируете украсить ArrayList , вы, вероятно, захотите, чтобы ваш подкласс ForwardingList также реализовал RandomAccess .


Пример: ListWithDefault

Вот (неполный!) Пример ForwardingList , который заменяет нулевые значения в делегате заданным значением по умолчанию.

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 для более полной реализации.

19
ответ дан 4 December 2019 в 09:11
поделиться

Вы должны реализовать метод delegate () 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;
    }
}
4
ответ дан 4 December 2019 в 09:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: