Я хотел бы реализовать метод, аналогичный subList (a, b), но это работает, когда a> b. subList (a, b) и subList (b, a) должны возвращать представление List в той же области, но по-разному повторяться и нумеруться. Представление в случае a> b должно быть отменено. Является ли это возможным?
Мое решение на данный момент довольно примитивно. Первая проблема заключается в том, что subList (a, b) в случае a> b не корректирует нумерацию соответственно (для remove
или get
использования методов). Но что более важно, обратное представление List на самом деле является копией здесь не фактического представления, и я не знаю, как это исправить.
@SuppressWarnings("serial")
class ReverseLinkedList <T> extends LinkedList<T>
{
ReverseLinkedList(final List<T> l)
{
super(l); // problem, I want a view not a copy
}
@Override
public Iterator<T> iterator()
{
return new Iterator<T>()
{
ListIterator<T> listIter = listIterator(size());
public boolean hasNext()
{
return listIter.hasPrevious();
}
public T next()
{
return listIter.previous();
}
public void remove()
{
listIter.remove();
}
};
}
}
@SuppressWarnings("serial")
class CleverList<T> extends LinkedList<T>
{
@Override
public List<T> subList(int fromIndex, int toIndex)
{
if ( fromIndex < toIndex )
{
return super.subList(fromIndex, toIndex);
}
else
{
return new ReverseLinkedList<T>(super.subList(toIndex-1,fromIndex-1));
}
}
}
Как это работает на данный момент:
CleverList<Integer> list = new CleverList<Integer>();
for ( int i=1; i<=10; ++i )
{
list.add(i);
}
List<Integer> listA = list.subList(2,8);
printList(listA);
// "3 4 5 6 7 8 " ok
List<Integer> listB = list.subList(8,2);
printList(listB);
// "7 6 5 4 3 2 " ok
listB.remove(2);
printList(listB);
// "7 6 5 3 2 " not ok, the point was to remove "5"
printList(list);
// "1 2 3 4 5 6 7 8 9 10 " not ok, nothing was removed
Одним из возможных решений является использование композиции вместо наследования. Это может выглядеть так:
class ReverseLinkedList<T> implements List<T> {
// A reference to the actual list.
private final List<T> list;
public ReverseLinkedList(final List<T> list) {
// Does not create a copy.
// Stores a reference to the original list instead.
this.list = list;
}
@Override
public T get(int index) {
// Adjusts the index and calls the method on an actual list.
return list.get(list.size() - 1 - index);
}
//And so on for all the other methods declared in the List interface...
}
Он делает именно то, что вам нужно: он не создает копию списка, переданного конструктору, и вы можете контролировать все методы (get, remove и т.д.) Для правильной настройки индекса. Недостатком этого подхода является количество кода, который вам нужно написать: каждый метод, объявленный в интерфейсе List
должен быть определен в классе ReverseLinkedList
.
List<X> reverse = original.clone(); Collections.reverse(reverse);
,
LinkedList
или он может просто реализоватьList
?