Можно ли реализовать метод, аналогичный subList (a, b), но это работает, когда a> b?

1

Я хотел бы реализовать метод, аналогичный 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
  • 0
    Ваш класс должен расширять LinkedList или он может просто реализовать List ?
  • 0
    @ user2040251 Я думаю, что List будет достаточно. Мне немного любопытно, хотя расширение LinkedList.
Теги:
data-structures
collections

1 ответ

3

Одним из возможных решений является использование композиции вместо наследования. Это может выглядеть так:

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.

  • 0
    Да, это лучшее решение. Это также дает вам полный контроль над тем, хотите ли вы, чтобы это было только для чтения или для сквозного просмотра исходного списка. Если вам не нужно представление, но копия подойдет, вы можете перейти к List<X> reverse = original.clone(); Collections.reverse(reverse); ,
  • 0
    а как насчет методов interator () и listIterator ()? не могли бы вы предложить их реализации?
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню