2014-12-22 3 views
1

Я хотел бы реализовать метод, аналогичный subList (a, b), но это работает, когда a> b. subList (a, b) и subList (b, a) должны возвращать представление List в той же области, но по-разному повторяться и нумеруться. Изображение в случае a> b должно быть отменено. Является ли это возможным?Возможно ли реализовать метод, аналогичный subList (a, b), но который работает, когда 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» или он может просто реализовать «Список»? – kraskevich

+0

@ user2040251 Я думаю, что списка будет достаточно. Мне немного любопытно расширение LinkedList. –

ответ

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

} 

Это именно то, что вам нужно: он не создает копию списка, переданного конструктору, и вы можете контролировать все методы (получить, удалить и т.д.), чтобы отрегулировать индекс правильно. Недостатком такого подхода является количество кода, который вам нужно написать: каждый метод, объявленный в интерфейсе List, должен быть определен в классе ReverseLinkedList.

+0

Да, это лучшее решение. Он также дает вам полный контроль над тем, хотите ли вы это как просмотр только для чтения или сквозное представление исходного списка. Если вам не нужно представление, но будет сделана копия, вы можете перейти на «Список reverse = original.clone(); Collections.reverse (обратный); '. –

+0

и как насчет методов interator() и listIterator()? могли бы вы предложить их реализации? –

+0

@infoholic_anonymous Почти так же, как и другие методы: создайте итератор фактического списка, а затем используйте предыдущие для реализации следующего (и наоборот), hasPrevious для hasNext и настройте индекс для всех операций, которые включают индекс. – kraskevich

Смежные вопросы