Java: как выполнить итерацию по списку ссылок отсортированным способом?

#java #sorting #collections #iterator

Вопрос:

Возможно ли повторно просмотреть объекты списка ссылок без его сортировки?

 class MyClasslt;Tgt; implements Iterablelt;Tgt; {   private LinkedListlt;Tgt; myList = new LinkedListlt;gt;();   @Override  public Iteratorlt;Tgt; iterator() {  return new Iteratorlt;Tgt;() {   @Override  public boolean hasNext() {  return false;  }   @Override  public T next() {  // SHOULD RETURN THE ELEMENTS OF MYLIST IN A SORTED WAY  return null;  }   };  } }  

В этом случае мы можем предположить, что объекты типа T имеют целое поле для сортировки

Комментарии:

1. Если hasNext возвращает false , то next не следует вызывать вообще.

Ответ №1:

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

Оба метода имеют свои издержки:

  • Вы можете сохранить индекс «текущего» индекса и найти следующий индекс, просматривая весь список, но это стоит процессора
  • Вы можете создать личную копию списка, отсортировать ее и вернуть этот новый список, но это требует больше памяти, и вам придется обновлять новый список на случай, если в исходном списке изменились значения.

Ответ №2:

Короткий ответ: Нет.

Сортировка-это своего рода поиск текущего минимума/максимума, вы никак не можете найти это, не пройдя через каждый элемент в списке, и, следовательно, вам нужно будет все это как-то отсортировать, способ сделать это-через a Heap , что означает дополнительную память, если вы не хотите сортировать сам список.

 @Override public Iteratorlt;Tgt; iterator() {  PriorityQueuelt;Tgt; heap = new PriorityQueuelt;gt;(list);  return new Iteratorlt;Tgt;() {   @Override  public boolean hasNext() {  return !heap.isEmpty();  }   @Override  public T next() {  return heap.poll();  }   }; }  

Комментарии:

1. Если тип «T» не реализуется Comparable , необходимо указать Comparator в конструкторе PriorityQueue .

Ответ №3:

Если тип T реализует Comparablelt;Tgt; , вы можете сделать вот так.

 static class MyClasslt;T extends Comparablelt;Tgt;gt; implements Iterablelt;Tgt; {   private LinkedListlt;Tgt; myList = new LinkedListlt;gt;();   @Override  public Iteratorlt;Tgt; iterator() {  return myList.stream().sorted().iterator();  } }  public static void main(String[] args) {  MyClasslt;Integergt; obj = new MyClasslt;gt;();  obj.myList.add(2);  obj.myList.add(0);  obj.myList.add(1);   for (int i : obj)  System.out.println(i);   System.out.println(obj.myList); }  

выход:

 0 1 2 [2, 0, 1]  

В качестве альтернативы вы можете передать компаратор через конструктор.

 static class MyClasslt;Tgt; implements Iterablelt;Tgt; {   private LinkedListlt;Tgt; myList = new LinkedListlt;gt;();  private final Comparatorlt;Tgt; comparator;   public MyClass(Comparatorlt;Tgt; comparator) {  this.comparator = comparator;  }   @Override  public Iteratorlt;Tgt; iterator() {  return myList.stream().sorted(comparator).iterator();  } }