2011-02-08 2 views
50

Так что я все еще достаточно новое для Java, и я играл с ArrayList-х - то, что я пытаюсь достичь, это способ сделать что-то вроде этого:Перемещение предметов вокруг в ArrayList

Item 1 
Item 2 
Item 3 
Item 4 

Итак, я пытаюсь переместить элементы в списке, если он уже не находится наверху, и в этом случае он останется прежним. Например, если пункт 3 был перенесен список будет:

Item 1 
Item 3 
Item 2 
Item 4 

Из моего небольшого понимания в данный момент я хотел бы что-то вдоль линий:

IF arrayname index is not equal to 0 
THEN move up 
ELSE do nothing 

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

ответ

94

я наткнулся на этот старый вопрос в моих поисках ответа, и я думал, что просто опубликовать решение, которое я нашел в случае, если кто-то проходит мимо, здесь смотря на то же самое.

Для замены 2 элементов, Collections.swap в порядке. Но если мы хотим, чтобы переместить больше элементов, есть лучшее решение, которое включает в себя творческое использование Collections.sublist и Collections.rotate, что я не думал о, пока я не видел, что это описано здесь:

http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#rotate%28java.util.List,%20int%29

Вот цитата, но идти туда и читать все это для себя тоже:

Обратите внимание, что этот способ с пользой может быть применен к подсписки, чтобы переместить один или несколько элементов в списке, сохраняя при этом порядок оставшегося элементы.Например, следующий стиль перемещает элемент по индексу J вперед в положение к (которое должно быть больше или равно -j):

Collections.rotate(list.subList(j, k+1), -1);

+2

В моем приложении это подшиблирование оказалось медленнее, чем описанный здесь метод remove/insert: http://stackoverflow.com/a/4938696/1025391 – moooeeeep

+2

'больше или равно (> =)'? как насчет '<='? – user25

15

Чтобы перемещаться вверх, удалите и затем добавьте.

Для удаления - ArrayList.remove и назначить возвращенный объект в переменной
Затем добавить этот объект обратно в нужный индекс - ArrayList.add(int index, E element)

http://download.oracle.com/javase/6/docs/api/java/util/ArrayList.html#add(int, E)

+2

Это единственное решение, которое на самом деле работает, чтобы изменить порядок элементов в ArrayList. Благодаря! – mpemburn

+1

Очень элегантный! – geekQ

+0

с удалением не движется, он меняет положение двух объектов (swap), перемещение - перемещение одного объекта между некоторыми другими двумя объектами – user25

52

простой замены является гораздо лучше для " перемещая что-то»в ArrayList:

if(i > 0) { 
    Item toMove = arrayList.get(i); 
    arrayList.set(i, arrayList.get(i-1)); 
    arrayList.set(i-1, toMove); 
} 

Поскольку ArrayList использует массив, если вы удалить элемент из ArrayList, он должен «сдвинуть» все элементы после этого элемента вверх, чтобы заполнить пробел в массиве. Если вы вставляете элемент, он должен переместить все элементы после этого элемента, чтобы освободить место для его вставки. Эти сдвиги могут стать очень дорогими, если ваш массив очень большой. Поскольку вы знаете, что хотите в итоге получить такое же количество элементов в списке, то выполнение свопа, как это, позволяет вам «перемещать» элемент в другое место в списке очень эффективно.

Как Крис кулачный и Михал Kreuzman указывают, есть даже удобный метод в классе Collections, чтобы уменьшить эти три строки кода в одном:

Collections.swap(arrayList, i, i-1); 
+0

Это замечательно, collection.swap кажется идеальным. Одна небольшая проблема ive заметила, что использование этого в верхней части списка вызывает исключение из-за пределов - оно все еще работает именно так, как я хотел, но есть ли способ остановить его выброс исключения из-за пределов? – user319940

+1

@ user319940 Привет, StriplingWarrior показал его в первом примере кода. Индекс i должен быть больше 0 'if (i> 0)' –

+0

Хех, глупый я, пытался с ним, а не если - спасибо еще раз всем. Надеюсь, этот пост также поможет другим в будущем. – user319940

23

вы можете попробовать этот простой код, Collections.swap (list, i, j) - это то, что вы ищете.

List<String> list = new ArrayList<String>(); 
    list.add("1"); 
    list.add("2"); 
    list.add("3"); 
    list.add("4"); 

    String toMoveUp = "3"; 
    while (list.indexOf(toMoveUp) != 0) { 
     int i = list.indexOf(toMoveUp); 
     Collections.swap(list, i, i - 1); 
    } 

    System.out.println(list); 
+2

+1 за использование универсального подхода. – Sid

0

Перемещение элемента по отношению друг к другу что-то Мне нужно было много в моем проекте. Поэтому я написал небольшой класс util, который перемещает элемент в списке в позицию относительно другого элемента. Вы можете использовать (и улучшить;))

import java.util.List; 

public class ListMoveUtil 
{ 
    enum Position 
    { 
     BEFORE, AFTER 
    }; 

    /** 
    * Moves element `elementToMove` to be just before or just after `targetElement`. 
    * 
    * @param list 
    * @param elementToMove 
    * @param targetElement 
    * @param pos 
    */ 
    public static <T> void moveElementTo(List<T> list, T elementToMove, T targetElement, Position pos) 
    { 
     if (elementToMove.equals(targetElement)) 
     { 
      return; 
     } 
     int srcIndex = list.indexOf(elementToMove); 
     int targetIndex = list.indexOf(targetElement); 
     if (srcIndex < 0) 
     { 
      throw new IllegalArgumentException("Element: " + elementToMove + " not in the list!"); 
     } 
     if (targetIndex < 0) 
     { 
      throw new IllegalArgumentException("Element: " + targetElement + " not in the list!"); 
     } 
     list.remove(elementToMove); 

     // if the element to move is after the targetelement in the list, just remove it 
     // else the element to move is before the targetelement. When we removed it, the targetindex should be decreased by one 
     if (srcIndex < targetIndex) 
     { 
      targetIndex -= 1; 
     } 
     switch (pos) 
     { 
      case AFTER: 
       list.add(targetIndex + 1, elementToMove); 
       break; 
      case BEFORE: 
       list.add(targetIndex, elementToMove); 
       break; 
     } 
    } 
3

Применение рекурсии для изменения порядка элементов в ArrayList

public class ArrayListUtils { 
      public static <T> void reArrange(List<T> list,int from, int to){ 
       if(from != to){ 
        if(from > to) 
         reArrange(list,from -1, to); 
         else 
         reArrange(list,from +1, to); 

        Collections.swap(list, from, to); 
       } 
      } 
    } 
2

Как писал Миккель перед тем Collections.rotate простой способ. Я использую этот метод для перемещения элементов вверх и вниз в списке.

public static <T> void moveItem(int sourceIndex, int targetIndex, List<T> list) { 
    if (sourceIndex <= targetIndex) { 
     Collections.rotate(list.subList(sourceIndex, targetIndex + 1), -1); 
    } else { 
     Collections.rotate(list.subList(targetIndex, sourceIndex + 1), 1); 
    } 
} 
1

Чтобы Move элемент в списке, просто добавьте:

// move item to index 0 
Object object = ObjectList.get(index); 
ObjectList.remove(index); 
ObjectList.add(0,object); 

К Swap два пункта в списке, просто добавьте:

// swap item 10 with 20 
Collections.swap(ObjectList,10,20); 
Смежные вопросы