2011-02-08 58 views
50

Así que estoy siendo bastante nuevo a Java y he estado jugando con ArrayList de - lo que estoy tratando de lograr es un método para hacer algo como esto:Mover elementos en torno a un ArrayList

Item 1 
Item 2 
Item 3 
Item 4 

Así que estoy tratando de mover elementos en la lista, a menos que ya esté en la parte superior, en cuyo caso se mantendrá igual. Por ejemplo, si el artículo 3 se trasladó la lista sería:

Item 1 
Item 3 
Item 2 
Item 4 

Desde mi pequeña comprensión en el momento entonces yo quiero algo a lo largo de las líneas de:

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

La parte estoy luchando con es la parte de "subir". Cualquier sugerencia o muestra de código de cómo se podría lograr esto es muy apreciada.

Respuesta

94

me encontré con esta vieja pregunta en mi búsqueda de una respuesta, y pensé que me acaba de publicar la solución que encontré en caso de que alguien pasa por aquí en busca de la misma.

Para intercambiar 2 elementos, Collections.swap está bien. Pero si queremos avanzar más elementos, hay una mejor solución que implique un uso creativo de Collections.sublist y Collections.rotate que yo no había pensado hasta que lo vi describe aquí:

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

He aquí una cita, pero ir allí y leer toda la cosa para usted también:

Tenga en cuenta que este método puede ser útilmente aplicada a sublistas para mover una o más elementos dentro de una lista, preservando el orden del restante elementos.Por ejemplo, el siguiente idioma mueve el elemento en el índice j hacia adelante a la posición k (que debe ser mayor o igual a j):

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

+2

En mi aplicación, esta rotación de sublista parecía ser más lenta que la de eliminar/insertar-enfoque que se describe aquí: http://stackoverflow.com/a/4938696/1025391 – moooeeeep

+2

'mayor que o igual (> =)'? ¿Qué pasa con '<='? – user25

15

Para avanzar, quitar y luego agregar.

de quitar - ArrayList.remove y asigne el objeto devuelto a una variable
Luego agregar este objeto de nuevo en el índice requerido - ArrayList.add(int index, E element)

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

+2

Ésta es la única solución que realmente funciona para cambiar el orden de artículos en ArrayList. ¡Gracias! – mpemburn

+1

¡Muy elegante! – geekQ

+0

con quitarlo no se mueve, está cambiando las posiciones de dos objetos (intercambio), moviendo - está moviendo un objeto entre otros dos objetos – user25

52

Un simple intercambio es mucho mejor para " mover algo hacia arriba" en un ArrayList:

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

Debido a un ArrayList utiliza una matriz, si eliminar un elemento de un ArrayList, tiene que "desplazar" todos los elementos después de ese elemento hacia arriba para llenar el espacio en la matriz. Si inserta un elemento, debe desplazar todos los elementos después de ese elemento para dejar espacio para insertarlo. Estos cambios pueden ser muy costosos si su matriz es muy grande. Como sabes que quieres terminar con el mismo número de elementos en la lista, hacer un intercambio como este te permite "mover" un elemento a otra ubicación en la lista de manera muy eficiente.

Como Chris Buckler y Michal Kreuzman señalan, incluso hay un método útil en la clase de las Colecciones de reducir estas tres líneas de código para uno:

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

Esto es genial, collections.swap parece ser perfecto. Un pequeño problema que he notado es que usar este algo en la parte superior de la lista causa una excepción fuera de límites. Todavía funciona como yo quería, pero ¿hay alguna forma de evitar que arroje una excepción fuera de límites? – user319940

+1

@ user319940 Hi StriplingWarrior lo mostró en la primera muestra de código. Índice que tengo que ser mayor que 0 'if (i> 0)' –

+0

je, tonto, lo estaba intentando con en vez de si - gracias una vez más a todos. Esperamos que esta publicación también ayude a otros en el futuro. – user319940

23

se puede probar este código simple, Collections.swap (lista, i, j) es lo que estás buscando.

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 por usar el enfoque genérico. – Sid

0

elemento móvil con respecto a la otra es algo Necesitaba mucho en un proyecto mío. Así que escribí una pequeña clase util que mueve un elemento de una lista a una posición relativa a otro elemento. Siéntase libre de utilizar (y mejorar;))

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

La aplicación de la recursividad para reordenar los elementos en un 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

Como Mikkel publicada antes Collections.rotate es una forma sencilla. Estoy usando este método para mover elementos hacia arriba y hacia abajo en una lista.

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

Para Move elemento en la lista sólo tiene que añadir:

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

Para Swap dos elementos de la lista sólo tiene que añadir:

// swap item 10 with 20 
Collections.swap(ObjectList,10,20); 
Cuestiones relacionadas