¿Cómo aleatorizar dos ArrayLists de la misma manera?

257

Tengo dos listas de arrays filelisty imgListque se relacionan entre sí, por ejemplo, "H1.txt" relacionado con "e1.jpg". ¿Cómo aleatorizar automáticamente la lista de imgListacuerdo con la aleatorización de fileList? Al igual que en Excel, si clasificamos cierta columna, la otra columna seguirá automáticamente?

String [] file = {"H1.txt","H2.txt","H3.txt","M4.txt","M5.txt","M6.txt"};
ArrayList<String> fileList = new ArrayList<String>(Arrays.asList(file));

String [] img = {"e1.jpg","e2.jpg","e3.jpg","e4.jpg","e5.jpg","e6.jpg"};
ArrayList<String> imgList = new ArrayList<String>(Arrays.asList(img));

//randomized files
Collections.shuffle(fileList);

salida después de la aleatorización, por ejemplo:

fileList = {"M4.txt","M6.txt","H3.txt","M5.txt","H2.txt","H1.txt"};

salida prevista:

 imgList = {"e4.jpg","e6.jpg","e3.jpg","e5.jpg","e2.jpg","e1.jpg"};
Jessy
fuente

Respuestas:

585

Use Collections.shuffle()dos veces, con dos Randomobjetos inicializados con la misma semilla:

long seed = System.nanoTime();
Collections.shuffle(fileList, new Random(seed));
Collections.shuffle(imgList, new Random(seed));

El uso de dos Randomobjetos con la misma semilla asegura que ambas listas se barajarán exactamente de la misma manera. Esto permite dos colecciones separadas.

Michael Borgwardt
fuente
121

Envuélvalos en otra clase para que pueda terminar con una sola matriz o con Listesos objetos.

public class Data {
    private String txtFileName;
    private String imgFileName;

    // Add/generate c'tor, getter/setter, equals, hashCode and other boilerplate.
}

Ejemplo de uso:

List<Data> list = new ArrayList<Data>();
list.add(new Data("H1.txt", "e1.jpg"));
list.add(new Data("H2.txt", "e2.jpg"));
// ...

Collections.shuffle(list);
BalusC
fuente
10
Esta es la solución orientada a objetos de Java. Quizás, cómo debería hacerse ... :)
Evan
22

El enfoque más simple es encapsular los dos valores juntos en un tipo que tenga tanto la imagen como el archivo. Luego construye una ArrayListde eso y baraja.

Eso también mejora la encapsulación, dándole la propiedad de que siempre tendrá la misma cantidad de archivos que imágenes automáticamente.

Una alternativa si realmente no le gusta esa idea sería escribir el código aleatorio usted mismo (hay muchos ejemplos de un shuffle modificado de Fisher-Yates en Java, incluidos varios en Stack Overflow, sospecho) y simplemente operar en ambas listas en al mismo tiempo. Pero recomiendo encarecidamente seguir el enfoque de "mejorar la encapsulación".

Jon Skeet
fuente
11

Podrías hacer esto con mapas:

Map<String, String> fileToImg:
List<String> fileList = new ArrayList(fileToImg.keySet());
Collections.shuffle(fileList);
for(String item: fileList) {
    fileToImf.get(item);
}

Esto recorrerá las imágenes en orden aleatorio.

jjnguy
fuente
5

Esto se puede hacer usando el método aleatorio:

private List<Integer> getJumbledList() {
     List<Integer> myArrayList2 = new ArrayList<Integer>();
        myArrayList2.add(8);
        myArrayList2.add(4);
        myArrayList2.add(9);
        Collections.shuffle(myArrayList2);
        return myArrayList2;
Rohit Goyal
fuente
4

En lugar de tener dos matrices de cadenas, tenga una matriz de una clase personalizada que contenga sus dos cadenas.

EboMike
fuente
3

Puede crear una matriz que contenga los números del 0 al 5 y mezclarlos. Luego use el resultado como una asignación de "oldIndex -> newIndex" y aplique esta asignación a sus dos matrices originales.

Mark Byers
fuente
2

No estoy totalmente seguro de lo que quiere decir con "automáticamente": puede crear un objeto contenedor que contenga ambos objetos:

clase pública FileImageHolder {String fileName; String imageName; // TODO: inserta cosas aquí}

Y luego poner eso en una lista de matriz y aleatorizar esa lista de matriz.

De lo contrario, necesitaría realizar un seguimiento de dónde se movía cada elemento en una lista, y moverlo también en el otro.

aperkins
fuente
2

A menos que haya una manera de recuperar el índice anterior de los elementos después de que se hayan barajado, lo haría de dos maneras:

A) Hacer otra lista multi_shuffler = [0, 1, 2, ..., file.size ()] y barajarla. Pase sobre él para obtener el orden de sus listas de archivos / imágenes barajadas.

ArrayList newFileList = new ArrayList (); ArrayList newImgList = new ArrayList (); para (i = 0; i

o B) Cree una clase StringWrapper para contener los nombres de archivo / imagen y combine las dos listas que ya tiene en una: ArrayList combineList;

ajwood
fuente