Question

I need to print the contents of a Vector in random order without duplicates in Java. I have this so far:

 for(int p = 0; p < v.size(); p++) {
        boolean print = true;
        int n = Math.abs(r.nextInt() % v.size());
        Vector<Integer> printed = new Vector<Integer>();
        if(printed.contains(n))
            print = false;
        if(print)
            System.out.println(v.elementAt(n));
        printed.addElement(n);
    }

where "v" is my String Vector and "r" is my random generator (seeded by the time). It prints in random order, but still prints duplicates.

Any suggestions?

Was it helpful?

Solution

Collections.shuffle(vector) Then take output and put it in a set (don't use SortedSet). You've now randomized and removed duplicates.

OTHER TIPS

You initialize your Vector like so:

Vector<Integer> printed = new Vector<Integer>();

and then you check if printed contains something:

if(printed.contains(n))

But, you just initialized printed to contain zero elements.

Thus, printed.contains(n) will always be false.

As such, print will never be set to false and all of the elements in v will be printed to the console.

First and foremost, there is no reason to use Vector. It has been effectively deprecated since Java 1.2, more than 15 years ago. Use ArrayList instead.

Note also that calling Random.nextInt() % max is an anti-pattern, breaking the randomness of your generator. Always call Random.nextInt(max) if you want an Integer in a smaller range than Random.nextInt() - the latter method is designed to do the right thing and give you an even distribution.


Ok, so you want to strip duplicates, and you also want to print in an arbitrary (or do you literally mean random?) order.

The easiest way to accomplish both goals is with a Set. Common Set implementations, notably HashSet, are explicitly unordered, meaning the order they are added in is not necessarily the order they are returned.

So you could simply do the following:

List<Integer> ls = ...;
for(Integer i : new HashSet<Integer>(ls)) {
  System.out.println(i);
}

However like I said, there is a difference between an arbitrary order, and properly random. HashSet is arbitrary, but there are potentially predictable patterns in its implementation, such that the output of the above code could not be called "random".

If you really want random ordering, your best bet is the Collections.shuffle() function, which takes a list and shuffles it, so that each element is approximately equally likely to be in any position in the list. Here's some example code (note we have to first put it through a HashSet to strip duplicates):

List<Integer> ls = ...;
ls = new ArrayList<Integer>(new HashSet<Integer>(ls));
Collections.shuffle(ls);
for(Integer i : ls) {
  System.out.println(i);
}

This will print the unique elements of ls in a random* order.

*Technically, it is pseudo-random, but there's no need to worry about that. It's random enough.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top