0

This is a chunk of code in Java, I'm trying to output random numbers from the tasks array, and to make sure none of the outputs are repeated, I put them through some other loops (say you have the sixth, randomly-chosen task "task[5]"; it goes through the for loop that will check it against every "tCheck" element, and while task[5] equals one of the tCheck elements, it will keep trying to find another option before going back to the start of the checking forloop... The tCheck[i] elements are changed at the end of each overall loop of output to the new random number settled on for the task element).

THE PROBLEM is that, despite supposedly checking each new random task against all tCheck elements, sometimes (not always) there are repeated tasks output (meaning, instead of putting out say 2,3,6,1,8,7,5,4, it will output something like 2,3,2,1,8,7,5,4, where "2" is repeated... NOT always in the same place, meaning it can sometimes end up like this, too, where "4" is repeated: 3,1,4,5,4,6,7,8)

int num = console.nextInt();                                
String[] tasks = {"1","2","3","4","5","6","7","8"};
String[] tCheck = {"","","","","","","",""};
for(int i = 0; i<= (num-1); i++){
    int tNum = rand.nextInt(8);
    for(int j = 0; j <=7; j++){
        if(tasks[tNum].equals(tCheck[j])){
            while(tasks[tNum].equals(tCheck[j])){
                tNum = rand.nextInt(8);
            }
            j = 0;
        }
    }
    tCheck[i] = tasks[tNum];
    System.out.println(tasks[tNum]+" & "+tCheck[i]);
}

None of the other chunks of code affect this part (other than setting up Random int's, Scanners, so on; those are all done correctly). I just want it to print out each number randomly and only once. to never have any repeats. How do I make it do that?

Thanks in advance.

KhAn SaAb
  • 5,248
  • 5
  • 31
  • 52
Ray25Lee
  • 65
  • 1
  • 2
  • 8
  • Possible duplicate of [Generating Unique Random Numbers in Java](http://stackoverflow.com/questions/8115722/generating-unique-random-numbers-in-java) – SomeJavaGuy May 11 '16 at 06:51
  • why are you not using List with contains method – KhAn SaAb May 11 '16 at 06:54
  • 1
    Why don't you just insert your new numbers in a `HashSet` instead of all these loops? Every time you generate a new one, you could just check if it already exists in the `HashSet` in `O(1)` time and if so, you could ignore it and generate a new one. – Lefteris008 May 11 '16 at 06:54
  • To answer all the "why aren't you ___" questions, I'm brand new to Java, I've never heard of either of those things you guys just said. – Ray25Lee May 11 '16 at 06:55
  • I think that thing Kevin posted might help; I'm still reading through it. – Ray25Lee May 11 '16 at 06:56
  • 1
    @Ray25Lee A [`HashSet`](https://docs.oracle.com/javase/7/docs/api/java/util/HashSet.html) is a `Set` that basically contains unique elements. When you insert a new element, the class takes care of all the checks to determine whether the element exists, in other words a `HashSet` **cannot** contain duplicates. By using this kind of data structure you could transform all your loops into just one, single if statement that checks whether the `HashSet` contains an element. – Lefteris008 May 11 '16 at 06:59
  • One of the suggestions in that link is to "Create an array of 100 numbers, then randomize their order". I did that and it isn't working. Does that method work at all? I've never had an issue with this before, I'm assuming I mistyped something this time and am just not seeing it. – Ray25Lee May 11 '16 at 07:02
  • I like the sound of the HashSet, Lefteris008. I'll look into that. Thank you for the recommendation! – Ray25Lee May 11 '16 at 07:03

3 Answers3

4

Firstly, don't use arrays. Use collections - they are way more programmer friendly.
Secondly, use the JDK's API to implement this idea:

  • randomise the order of your elements
  • then iterate over them linearly

In code:

List<String> tasks = Arrays.asList("1","2","3","4","5","6","7","8");
Collections.shuffle(tasks);
tasks.forEach(System.out::println);

Job done.

Bohemian
  • 412,405
  • 93
  • 575
  • 722
  • This looks incredibly helpful; I tried putting it into a test program, and the "::" part is keeping it from compiling (I've never seen that type of formatting before, I'm not sure how to fix it). – Ray25Lee May 11 '16 at 07:09
  • @Ray25Lee that´s just a casual for loop, but it´s using the lambda way of writing it which was inclued in `java 8`. If you don´t use `java 8` you can simply rewrite that as a normal `for(String s : tasks)....`. – SomeJavaGuy May 11 '16 at 07:13
  • Nice using the lamba for Java 8, I keep forgetting about them !! @Ray25Lee, check your Java version. – AxelH May 11 '16 at 07:13
  • 2
    @Ray if you're not using java 8, try `for (String task : tasks) System.out.println(task);` instead – Bohemian May 11 '16 at 07:14
  • It works! Thanks guys. This is a fantastic way to do it (you're right, way easier). – Ray25Lee May 11 '16 at 08:33
0

you can check if a certain value is inside your array with this approach.

   for(int i = 0; i<= (num-1); i++){
    int tNum = rand.nextInt(8);
     boolean exist =   Arrays.asList(tasks).contains(tNum);
      while(!exist){
     //your code
     int tNum = rand.nextInt(8);
    exist =   Arrays.asList(tasks).contains(tNum);
  }       
}

if you are using an arraylist then you can check it with contains method since you are using an array we have to get the list from the array using asList() and then use the contains method. with the help of the while loop it will keep generating random numbers untill it generates a non duplicate value.

Priyamal
  • 2,919
  • 2
  • 25
  • 52
  • This is really expensive for big lists. **contains** loops on the list until it find the value or reach the end, this could be expensive really fast. – AxelH May 11 '16 at 07:15
0

I used to created something similar using an ArrayList

public class Main {
    public static void main(String[] args) {

        String[] array = { "a", "b", "c", "d", "e" };
        List<String> l = new ArrayList<String>(Arrays.asList(array));
        Random r = new Random();
        while(!l.isEmpty()){
            String s = l.remove(r.nextInt(l.size()));
            System.out.println(s);
        }
    }
}

I remove a random position in the list until it's empty. I don't use any check of content. I believe that is kind of effective (Even if I create a list)

AxelH
  • 14,325
  • 2
  • 25
  • 55