Solved Generate 3 Unique Numbers between 1 - 8

Discussion in 'Spigot Plugin Development' started by Dusk_2_Dawn, Feb 21, 2020.

  1. Okay, first of all, I know this may sound completely stupid. There is most likely some simple Java trick that I am missing with this and I just can't figure it out. I'm posting here because this is just driving me crazy.

    Anyways, so the title pretty much says it all. I'm created a plugin and I am working on a quest system in it currently. I'm trying to give the player 3 unique quests (So no duplicates). I can get the random number just fine, it's just that I am struggling with the unique part. I've tried some things like adding the number to a list and checking if it creates a duplicate, and then creating a new one if it is. The problem with this is I don't have an efficient way to recheck this new number after I create it (On the off chance that it creates another duplicate)

    Can someone help me?
     
  2. Perhaps you can try to keep track of the quests/numbers a player currently has with a hashmap or something like that?
    Then just refer to the values of the player in your hashmap when creating a new random number.
     
  3. You can simplified use Random and store the number in an array.
    When you create the next number, just check if it's already in the array otherwise create a new number
    That's it.
     
  4. That's what I'm doing. It's just that I want to check if that newly created number has already been used just in case it's still a duplicate.
     
  5.  
  6. Yes, I get that, but how do I do that efficiently. I don't want a million if's or anything like that.
     
  7. I think you’re worrying about it being slow to reroll the number. That’s not even close to slow, each random call is like 4 mathematical operations. Your modern consumer CPU can do between 1 billion and 6 billion (on the lower end) mathematical operations per second.
     
  8. That's not what I'm worried about. I want my work to be as clean as possible and having a bunch of if statements for just a random number isn't very clean in my opinion. I just want something simple and efficient
     
  9. That is the cleanest possible solution, a while statement and checking an array is clean.
     
  10. Code (Java):
        public static List<Integer> randomNumbers(int min, int max, int amount) {
            List<Integer> numbers = new ArrayList<>();
            Random random = new Random();
            int num = 0;

            for (int i = 0; i < amount; i++) {
                do {
                    num = random.nextInt(max) + 1;
                } while (numbers.contains(num));
                numbers.add(num);
            }
            return numbers;
        }
     
  11. FrostedSnowman

    Resource Staff

    If you are only checking for temporary uniqueness, that is, within the generation itself and not with previously stored values, you could utilize ThreadLocalRandom's IntStream feature. For example, this will generate 5 random unique numbers between 0 and 10--inclusive of 0:

    Code (Java):
    ThreadLocalRandom.current()
            .ints(0, 10)
            .distinct()
            .limit(5)
            .forEach(num -> Bukkit.broadcastMessage(Integer.toString(num)));
    Note that the starting bound is inclusive, the ending is exclusive.
     
    • Winner Winner x 1
    • Useful Useful x 1
  12. Thank you! It works perfectly!
     
  13. If you want speed, I have runed this code
    Code (Java):
    public static void main(String[] args) {
            test(100).forEach(System.out::println);
        }

        public static List<String> test(int times) {
            List<String> test = new ArrayList<>();

            for (; times > 0; times--) {
                long mil1 = System.currentTimeMillis();
                ThreadLocalRandom.current().ints(0, 150).distinct().limit(100).forEach(System.out::println);
                long mil2 = System.currentTimeMillis();
                randomNumbers(0, 150, 100).forEach(System.out::println);
                long mil3 = System.currentTimeMillis();
                test.add("ThreadLocalRandom: "+ (mil2 - mil1) + "   randomNumbers: " + (mil3 - mil2));
            }

            return test;
        }

        public static List<Integer> randomNumbers(int min, int max, int amount) {
            List<Integer> numbers = new ArrayList<>();
            Random random = new Random();
            int num = 0;

            for (int i = 0; i < amount; i++) {
                do {
                    num = random.nextInt(max) + 1;
                } while (numbers.contains(num));
                System.out.println(i + " / " + amount);
                numbers.add(num);
            }
            return numbers;
        }
    And this are the results
    Code (Text):
    ThreadLocalRandom: 114   randomNumbers: 11
    ThreadLocalRandom: 4   randomNumbers: 8
    ThreadLocalRandom: 4   randomNumbers: 4
    ThreadLocalRandom: 2   randomNumbers: 3
    ThreadLocalRandom: 2   randomNumbers: 3
    ThreadLocalRandom: 2   randomNumbers: 4
    ThreadLocalRandom: 3   randomNumbers: 2
    ThreadLocalRandom: 2   randomNumbers: 2
    ThreadLocalRandom: 3   randomNumbers: 3
    ThreadLocalRandom: 3   randomNumbers: 6
    ThreadLocalRandom: 1   randomNumbers: 4
    ThreadLocalRandom: 2   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 2   randomNumbers: 2
    ThreadLocalRandom: 2   randomNumbers: 2
    ThreadLocalRandom: 2   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 2   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 4
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 2   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 3
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 4
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 3   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 2   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 2   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 4   randomNumbers: 4
    ThreadLocalRandom: 5   randomNumbers: 1
    ThreadLocalRandom: 2   randomNumbers: 1
    ThreadLocalRandom: 2   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 3   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 2   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 4
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 2   randomNumbers: 1
    ThreadLocalRandom: 0   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 3
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 0   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 4
    ThreadLocalRandom: 2   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 7
    ThreadLocalRandom: 0   randomNumbers: 3
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 4   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 35
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 10
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 0   randomNumbers: 14
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 0   randomNumbers: 2
    ThreadLocalRandom: 0   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 0   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 2
    ThreadLocalRandom: 0   randomNumbers: 2
    ThreadLocalRandom: 1   randomNumbers: 1
    ThreadLocalRandom: 1   randomNumbers: 1
    If you are going to generate 3 random numbers ones, is beter to use my code, if you are going to generate tree random numbers a lot of times is beter FrostedSnowman's code