Maor Cohen
Maor Cohen

Reputation: 956

random elements from a list DURING the addition

There are 20 names in my code. my function has 2 options to add elements to a list I've:

1.

Inserting all the 20 names to the list:

public void addNames() {
    list.add("name1");
    list.add("name2");
    ...
    list.add("name20");
}

2.

Adding only 5 random names(from the 20 names) to the list. For doing it, I thought about 2 ways. What's the best way to random 5 names from the 20? maybe you have a better way.

A.

Using a random set of indices (each value will be between 0 to 19 because there are 20 names) and before the 'add' I'll check if adding them or not by some counter:

public void addNames() {
    // adding 5 random indices between 0 to 19 to the set
    Set<Integer> set = new HashSet<Integer>();
    Random r = new Random();
    Set<Integer> indices = new HashSet<>(numRandomNames); //==5
    for (int i = 0; i < numRandomNames; ++i) {
        int index = r.nextInt(numNames - 0); //==19
        indices.add(index);
    }

    int counter = 0;
    if (indices.contains(counter)) {
        list.add("name1");
    }
    counter++;
    if (indices.contains(counter)) {
        list.add("name2");
    }
    counter++;
    if (indices.contains(counter)) {
        list.add("name3");
    }
    ...
}

B.

RandomList that extends List and overrides the 'add' function to do the same as 'A.' does BUT the override 'add' will decide whether adding the value inside the function so my function will look the same as 1. with the override 'add' function

Do you think about a better solution? if not, then which one is better? (A or B?). I just saw that people recommends not to extend the java collection but I think it's the best solution from these 2 solutions.

NOTE

====

my code can have 10000 names or more even so I don't want to add all the 10,000 names to this\other list and then random 5 of them to other list. I prefer to do it DURING the addition in order to avoid many places of the list while I don't really need them.

EDIT

an answer to ProgrammerTrond:

I'm not sure I'll do it but what I asked me to show is my suggestion of 2.B:

public class RandomList<Integer> implements List<Integer> {
    private int addCallsCounter;
    private Set<Integer> setIndices = null;

    public RandomList(final int numElements, final int maxVal, final int minVal) {
        addCallsCounter = 0;
        setIndices =  new HashSet<Integer>(numElements);
        Random r = new Random();
        while (setIndices.size() < numElements) {
            int index = r.nextInt(maxVal - minVal + 1) + minVal;
            if (setIndices.contains(index) == false) {
                setIndices.add(index);
            }
        }
    }

    @Override
    public boolean add(Integer object) {
        if (setIndices.contains(addCallsCounter++)) {
            this.add(object);
            return true;
        }
        return false;
    }
}

and from my code I'll do so:

RandomList randList = new RandomList(5);
randList.add("name1");
randList.add("name2");
randList.add("name3");
...
randList.add("name19");
randList.add("name20");

but my problem is that I need to implement MANY abstract methods of List pfff. RandomList cann't be abstract too because then it won't be able to be instantiated.

Upvotes: 0

Views: 61

Answers (2)

Programmer Trond
Programmer Trond

Reputation: 313

Why not like this? You don't need the random index list in your list implementation. Didn't you just want a method that would add to a list 5 random names drawn from a set of available names?

import java.util.*;
public class ListAdding {

    private static List<String> allNames = Arrays.asList("name1", "name2", "name3", "name4", "name5", "name6", "name7");

    public static void main(String[] args) {
        new Temp().test();
    }

    void test() {
        List<String> list = new ArrayList<>();
        list.add("Bernie");
        addFiveRandom(list);
        for (int i = 0; i < list.size(); i++) {
            System.out.println(i + ": " + list.get(i));
        }
        // Example: 0: Bernie
        // 1: name2
        // 2: name3
        // 3: name6
        // and so on  
    }

    void addFiveRandom(List<String> toBeAddedTo) {
        List<Integer> indices = new ArrayList<>();
        while (indices.size() < 5) {
            int newIndex = new Random().nextInt(5);
            if (!indices.contains(newIndex))
                indices.add(newIndex);
        }
        for (Integer index : indices) {
            toBeAddedTo.add(allNames.get(index));
        }
    }
}

Upvotes: 0

Rajesh Gosemath
Rajesh Gosemath

Reputation: 1872

try this:

List<Integer> index = new ArrayList<>();
List<String> five_names = new ArrsyList<>();
List<String> allnames = new ArrayList<>();

store five random values

for(int i = 0;i < 5;i++){

  int index_no = getrandomNumber();
  index.add(index_no);
  five_names.add(allnames.get(index_no));
}

getRandomNumber method:

public int getRandomNumber(){

    Random rnd = new Random();
    int x = rnd.nextInt(20);

    if(index.contains(x)){
       return getRandomNumber();
    }else{
       return x
    }
 }

Upvotes: 1

Related Questions