Я ищу пример кода, который объясняет класс Guava ForwardingList. По сути, я реализую собственный класс ArrayList, который будет использоваться для решения этого требования, упомянутого в моего предыдущего вопроса SO . Я никогда не использовал коллекцию Google раньше. Но, просто взглянув на JavaDoc ForwardingList , Я думаю, что я могу реализовать свой собственный класс путем подкласса ForwardingList.
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
для более полной реализации.
Вы должны реализовать метод 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;
}
}