有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

带有随机种子的Java树映射没有固定的大小

我想用它生成10个Udisk实例,价格和容量都是随机的

// test.java
import java.util.*;

class Udisk {
    float price;
    int capacity;
    Udisk(float p, int c) {
        this.price = p;
        this.capacity = c;
    }
    @Override
    public String toString() {
        return "Udisk price: "+this.price+" capacity: "+this.capacity;
    }
}

class Main {
    public static void main(String[] args) {
        Map<Float, Udisk> tm = new TreeMap<Float, Udisk>();
        for(int count=0; count < 10; count++) {
            Random rand = new Random(System.currentTimeMillis());
            float price = Math.abs(rand.nextInt())%100;
            int capacity = Math.abs(rand.nextInt())%10;
            Udisk u = new Udisk(price, capacity);
            tm.put(u.price, u);
        }
        System.out.println(tm+ " "+tm.size());
    }
}

javac test.java之后,我运行了几次java Main,结果非常奇怪

First Time: {3.0=Udisk price: 3.0 capacity: 1} 1
Second Time: {33.0=Udisk price: 33.0 capacity: 8, 86.0=Udisk price: 86.0 capacity: 0} 2
Third Time: {46.0=Udisk price: 46.0 capacity: 8} 1
Fourth Time: {24.0=Udisk price: 24.0 capacity: 1, 73.0=Udisk price: 73.0 capacity: 5} 2

所有这些结果在树状图中只有不到10项。将代码更改为

import java.util.*;

class Udisk {
    float price;
    int capacity;
    Udisk(float p, int c) {
        this.price = p;
        this.capacity = c;
    }
    @Override
    public String toString() {
        return "Udisk price: "+this.price+" capacity: "+this.capacity;
    }
}

class Main {
    public static void main(String[] args) {
        Map<Float, Udisk> tm = new TreeMap<Float, Udisk>();
        for(int count=0; count < 10; count++) {
            Random rand = new Random(System.currentTimeMillis());
            float price = Math.abs(count)%100;
            int capacity = Math.abs(count)%10;
            Udisk u = new Udisk(price, capacity);
            tm.put(u.price, u);
        }
        System.out.println(tm+ " "+tm.size());
    }
} 

答案是正确的

{0.0=Udisk price: 0.0 capacity: 0, 1.0=Udisk price: 1.0 capacity: 1, 
2.0=Udisk price: 2.0 capacity: 2, 3.0=Udisk price: 3.0 capacity: 3, 
4.0=Udisk price: 4.0 capacity: 4, 5.0=Udisk price: 5.0 capacity: 5, 
6.0=Udisk price: 6.0 capacity: 6, 7.0=Udisk price: 7.0 capacity: 7, 
8.0=Udisk price: 8.0 capacity: 8, 9.0=Udisk price: 9.0 capacity: 9} 10

我想知道我在随机中错过了什么导致了前一个问题,谢谢你的帮助


共 (1) 个答案

  1. # 1 楼答案

    对此有一些想法:

    a)在循环中初始化随机数的代价很高——你总是初始化一个新的随机伪随机数序列,而你也可以把随机创建从循环中拉出来完成

    b)贵方价格为整数模100->;只有100个可能的值,因此可能会出现键冲突(在这种情况下,10次迭代不会创建10个不同的元素)

    最重要的是

    c)System.currentTimeMillis()可能太慢了。你的循环只会创建一个对象并将其放入地图中——这非常、非常快(即使使用随机种子)。 这可能是由于System.currentTimeMillis()在迭代之间没有改变(请参见a),所以您只需使用相同的种子值来初始化伪随机序列。同一种子的随机数产生相同的序列。因此,除非你的System.currentTimeMillis()在迭代之间发生变化(在某些系统上,这种变化只会每15毫秒发生一次),否则你最终只能得到一个或最多两个不同的价格值

    尝试将随机数从循环中拉出:

        Random rand = new Random(System.currentTimeMillis());
        for(int count=0; count < 10; count++) {
            float price = Math.abs(rand.nextInt())%100;
            int capacity = Math.abs(rand.nextInt())%10;
            Udisk u = new Udisk(price, capacity);
            tm.put(u.price, u);
        }
    

    现在你应该接近10个值。然而,你可能会运气不好,画两次相同的nextInt()值——因此,如果你需要正好10个值,我建议让循环条件:

        Random rand = new Random(System.currentTimeMillis());
        while(tm.size() < 10) {
            float price = Math.abs(rand.nextInt())%100;
            int capacity = Math.abs(rand.nextInt())%10;
            Udisk u = new Udisk(price, capacity);
            tm.put(u.price, u);
        }
    

    祝你好运