267

I have two arraylist filelist and imgList which related to each other, e.g. "H1.txt" related to "e1.jpg". How to automatically randomized the list of imgList according to the randomization of fileList? Like in excel, if we sort certain column, the other column will automatically follow?

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);

output after randomization e.g.:

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

intended output:

 imgList = {"e4.jpg","e6.jpg","e3.jpg","e5.jpg","e2.jpg","e1.jpg"};
regapictures
  • 371
  • 3
  • 12
Jessy
  • 15,321
  • 31
  • 83
  • 100

9 Answers9

597

Use Collections.shuffle() twice, with two Random objects initialized with the same seed:

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

Using two Random objects with the same seed ensures that both lists will be shuffled in exactly the same way. This allows for two separate collections.

Nathan
  • 8,093
  • 8
  • 50
  • 76
Michael Borgwardt
  • 342,105
  • 78
  • 482
  • 720
122

Wrap them in another class so that you can end up with a single array or List of those objects.

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

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

Usage example:

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
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • 10
    This is the Java, object oriented solution. Perhaps, how it should be done... :) – Evan Feb 05 '13 at 00:45
22

The simplest approach is to encapsulate the two values together into a type which has both the image and the file. Then build an ArrayList of that and shuffle it.

That improves encapsulation as well, giving you the property that you'll always have the same number of files as images automatically.

An alternative if you really don't like that idea would be to write the shuffle code yourself (there are plenty of examples of a modified Fisher-Yates shuffle in Java, including several on Stack Overflow I suspect) and just operate on both lists at the same time. But I'd strongly recommend going with the "improve encapsulation" approach.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
11

You could do this with maps:

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

This will iterate through the images in the random order.

jjnguy
  • 136,852
  • 53
  • 295
  • 323
5

This can be done using the shuffle method:

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
  • 550
  • 8
  • 9
4

Instead of having two arrays of Strings, have one array of a custom class which contains your two strings.

EboMike
  • 76,846
  • 14
  • 164
  • 167
3

You can create an array containing the numbers 0 to 5 and shuffle those. Then use the result as a mapping of "oldIndex -> newIndex" and apply this mapping to both your original arrays.

Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
2

Not totally sure what you mean by "automatically" - you can create a container object that holds both objects:

public class FileImageHolder { String fileName; String imageName; //TODO: insert stuff here }

And then put that in an array list and randomize that array list.

Otherwise, you would need to keep track of where each element moved in one list, and move it in the other one as well.

aperkins
  • 12,914
  • 4
  • 29
  • 34
2

Unless there's a way to retrieve the old index of the elements after they've been shuffled, I'd do it one of two ways:

A) Make another list multi_shuffler = [0, 1, 2, ... , file.size()] and shuffle it. Loop over it to get the order for your shuffled file/image lists.

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

or B) Make a StringWrapper class to hold the file/image names and combine the two lists you've already got into one: ArrayList combinedList;

ajwood
  • 18,227
  • 15
  • 61
  • 104