0

Let's say I want to generate 20 random numbers on a 8 by 6 grid.(8 columns, 6 rows) . Based on the answer from here:Creating random numbers with no duplicates, I wrote my code like this:

Random randomNumGenerator = new Random();
Set<Integer[][]> generated = new LinkedHashSet<Integer[][]>();
while (generated.size() < 20) {
    int randomRows = randomNumGenerator.nextInt(6);
    int randomColumns = randomNumGenerator.nextInt(8);
    generated.add(new Integer[][]{{randomRows,randomColumns}});
}

In reality what happens is the Set see Integer[][]{{5,5}}; and Integer[][]{{5,5}};as NOT duplicate.Why? Even tho my purpose is to get 20 non-duplicate pair of numbers, this does not work. How do I fix this?

Community
  • 1
  • 1
OPK
  • 4,120
  • 6
  • 36
  • 66
  • 2
    You have to wrap the pair in a bean and override hashCode() and equals() methods – rafalopez79 Aug 02 '15 at 20:16
  • 1
    even if the arrays contain the same elements, they are different objects in memory – Buda Gavril Aug 02 '15 at 20:31
  • I'm confused by your code... It looks like your Set is a set of two dimensional arrays of Integer. So if you want a whole bunch of these grids then I guess you could do it this way, but I think you want just one grid, right? – Jim Archer Aug 02 '15 at 20:33

3 Answers3

1

Array equals is == in Java, so an array is only equal to itself. Normaly you use Arrays.equals(array1, array2) to compare them by content, but in this case, arrays are simply the wrong choice. You can either create a bean, as rafalopez79 suggested of use an array of Collections (List in your case), as a List will compare the content on equals, see the documentation. Choice is pretty much yours, a bean would probably be a bit cleaner.

Florian Schaetz
  • 10,454
  • 5
  • 32
  • 58
1

The Set checks for duplicates using the equals method (and also the hashCode method) of its inner type, but the Integer[][]'s equals method compares the memory addresses and not the contents.

Why do you use a Set of Integer[][] if you just want to store pairs? Unfortunately, in Java there is no Pair class, but if you do not want to create your own, you can use the Map.Entry for that.

Random randomNumGenerator = new Random();
Set<Map.Entry<Integer, Integer>> generated = new LinkedHashSet<>();
while (generated.size() < 20) {
    int randomRows = randomNumGenerator.nextInt(6);
    int randomColumns = randomNumGenerator.nextInt(8);
    generated.add(new AbstractMap.SimpleEntry<>(randomRows,randomColumns));
}
System.out.println(generated);
Helder Pereira
  • 5,522
  • 2
  • 35
  • 52
0

How about this code. I ran it through the debugger, it works nicely and yes, the contains() method checks the value of the Integer, not the reference. You can change the range of the random number as needed, I used 5 to facilitate testing. Yes I know it's not very robust, as written this will be an endless loop (because of the limited range of 5) but it's a simple example to make the point.

UPDATE: Actually this has a bug in that it won't check for uniqueness across all the rows, but that's easily fixed as well. I just re-read the original question and looking at the original code I'm not sure I know what you want exactly. If you just want a grid with 48 unique Intergers arranged 8 by 6 this will do it, but there are several ways to do this.

    final int rows = 6;
    final int cols = 8;

    Random randomGenerator = new Random();


    ArrayList[] grid = new ArrayList[rows];

    for(int i=0; i<rows; i++)
    {
        grid[i] = new ArrayList<Integer>();

        for(int j=0; j<cols; j++)
        {
            for(;;)
            {
                Integer newInt = new Integer(randomGenerator.nextInt(5));               
                if(!grid[i].contains(newInt))
                {
                    grid[i].add(newInt);
                    break;
                }   
            }

        }
    }
Jim Archer
  • 1,337
  • 5
  • 30
  • 43