user1583209 user1583209 - 1 month ago 10
Java Question

Create random values of generic type in Java

I have the following:

public class RandomList {

private List<Integer> list;

public List<Integer> getList() {
return list;
}

public RandomList (int n) {
list = new ArrayList<Integer>();

Random rand = new Random();
rand.setSeed(System.currentTimeMillis());

for (int i=0; i < n; i++)
{
Integer r = rand.nextInt();
list.add(r);
}
}
}


which gives me a list filled with random Integer values. I would like to generalize this, to also get a list of random Character values or perhaps lists of other types' random values.

So what I want is a generic type version,
class RandomList<T>
. I can replace everywhere "Integer" by "T", but am stuck at the line
Integer r = rand.nextInt();
which would read different for different types.

I am thinking of doing the following:


  1. pass in the class of the generic type to RandomList

  2. using
    instanceof
    check the passed in class against the desired types (Integer, Character...) and depending on the check return the proper random value



Does this make sense? Is there another/better way to achieve what I want?

Answer

First method (inferior)

In Java you can't check for the generic type, at least not without reflection. You're on the money with the generic type, so you'd do something like this:

public class RandomList<T> {
    private List<T> list;
    private Class<T> clazz;

    public List<T> getList() {
        return list;
    }

    public RandomList (Class<T> clazz, int n) {
        this.clazz = clazz;
        list = new ArrayList<T>();

        Random rand = new Random();
        rand.setSeed(System.currentTimeMillis());

        if (clazz.isAssignableFrom(Integer.class)) {
            for (int i = 0; i < n; i++) {
                Integer r = rand.nextInt();
                list.add(r);
            }
        }
        else {
            throw new IllegalArgumentException("Unsupported class: " + clazz.getName());
        }
    }
}

Second method (superior)

Alternatively, you could generalise this even further and add a Function to produce the randomised results. Note that this requires Java 8. If you're not on Java 8, you could just define an interface and construct that anonymously.

public class RandomList<T> {
    private List<T> list;

    public List<T> getList() {
        return list;
    }

    public RandomList (Function<Random, T> creator, int n) {
        list = new ArrayList<T>();

        Random rand = new Random();
        rand.setSeed(System.currentTimeMillis());

        for (int i = 0; i < n; i++) {
            list.add(creator.apply(rand));
        }
    }
}

Construct a new instance using:

RandomList<Integer> list = new RandomList<>(rand -> rand.nextInt(), 10);

Third method (cleaner)

Edit: This occurred to me later, but you seem to be using Java 8, so you could just use streams:

List<Integer> list = Stream.generate(() -> rand.nextInt()).limit(10).collect(Collectors.toList())