0

我创建了一种随机化列表的方法:

public <T> List<T> randomize(List<T> list) {
    LinkedList<T> randomizedList = new LinkedList<>();
    Random random = new Random(list.size());
    for (int i = random.nextInt(); i < list.size(); i++) {
        randomizedList.add(list.get(i));
    }
    return randomizedList;
}

我传递给此方法的列表包含例如五个元素。当我创建Random random = new Random(list.size());时,我期望当我调用它时random.nextInt()它会返回随机整数,这将是列表元素的索引。

但是,当我调用random.nextInt();而不是从间隔返回数字[0, 4](我希望返回)时,它会返回 for eg: 的值-349120689。这给了我一个java.lang.IndexOutOfBoundsException: Index: -349120689, Size: 5.

为什么会发生这种情况以及如何解决这个问题?

4

5 回答 5

3
  1. new Random(list.size());这会将随机数生成器的种子设置为list.size();我建议更改为new Random()(这将根据系统的当前时间为您提供种子)。不过,最好始终重用同一个 Random 对象。

  2. random.nextInt();这里是你想放的地方random.nextInt(list.size());,它会给你一个从 0 到 list.size() - 1 的数字。

  3. 即使进行了上述更改,您的代码也只会为您提供列表的子列表,该列表从随机索引开始直到结束。改为使用Collections.shuffle(list)

要进行真正的洗牌,您需要“记住”您插入了哪些元素。在伪代码中,您可以执行以下操作:

  • 将原始列表复制到一个新列表中,我们称之为“orig”
  • 创建一个新的空列表,我们称之为“结果”
  • 只要 orig 列表有元素,就在随机索引处获取一个元素并将其添加到结果列表中。从 orig 列表中删除所选元素。
  • 返回结果列表。
于 2013-02-08T12:24:26.367 回答
2

我希望当我调用 random.nextInt() 时它会返回随机整数,这将是列表元素的索引。

您误解了Random(long)构造函数的目的。该构造函数的目的是为列表指定一个种子。你不想这样做——这意味着每个大小为 5 的集合总是以相同的方式洗牌。

您指定每次调用的范围nextInt。因此,如果您想要一个介于 0(包括)和max(不包括)之间的随机数,您只需使用:

int value = random.nextInt(max);

但是,最好只使用Collections.shuffle而不是编写自己的代码来执行此操作-假设您真的想要一个随机播放(无论如何,这不是您当前的方法会给您的-即使在修复nextInt呼叫之后,您也会结束基本上是一个子列表,因为nextInt()只调用一次。所以如果第一次调用nextInt()返回 2(在 5 个列表中),你最终会返回一个包含最后 3 个元素的新列表。我强烈怀疑这不是你试图做。

附带说明一下,如果您想知道 API 的行为为何不符合您的预期,请阅读文档Random(long)构造函数的文档Random.nextInt()很明显不是您所期望的行为。

于 2013-02-08T12:24:53.157 回答
0

用这个

public <T> List<T> randomize(List<T> list) {
    LinkedList<T> randomizedList = new LinkedList<>();
    Random random = new Random();
    for (int i = random.nextInt(list.size()); i < list.size(); i++) {
        randomizedList.add(list.get(i));
    }
    return randomizedList;
}
于 2013-02-08T12:23:41.077 回答
0

构造函数的参数Random是一个随机种子,而不是它返回的最大值。

将最大数量传递给nextInt()

于 2013-02-08T12:24:03.333 回答
0

您将nextInt(n)(随机化的上限)的参数与构造函数的参数(随机种子)混淆了。您应该使用nextInt(list.size),并且可能使用 初始化 Random 对象new Random()

于 2013-02-08T12:24:12.823 回答