4

看起来我既不能使用 ArrayList 也不能​​使用 Set:

  • Set<>- 我可以使用一组来避免重复,但没有随机播放选项//Collections.shuffle(List<?> list)

  • ArrayList<>- 我可以使用 shuffle 来随机化列表,但允许重复。

我可以使用 aSet并将其转换为 a ArrayList(或相反)以避免重复。或者,循环遍历集合以随机化项目。但我正在寻找更有效的东西。

4

5 回答 5

3

您可以维护两个单独的集合, anArrayList和 a HashSet,并拒绝插入HashSet.

如果您关心封装,请将两个集合包装在一个实现的元对象中List,并仔细记录重复元素的插入将被拒绝,即使一般合同List没有这样规定。

谈到这个解决方案的成本,我相信就时间而言,如果与普通的相比,成本绝对可以忽略不计ArrayList:s 成本摊销 O(1) 上的大多数操作HashSet,即查找和插入。另一方面,您的内存使用量将是两倍(或更多,取决于HashSet负载因子)。

于 2013-02-15T10:58:33.597 回答
1

据我所知,套装没有排序,所以你显然不能洗牌。为了从列表中删除重复项,我发现:如何从 ArrayList 中删除重复的元素?.

于 2013-02-15T10:57:35.027 回答
0

您实际上可以使用“有序集”,例如 TreeSet。为了获得随机顺序,不要插入实际项目,而是插入具有随机重量的包装器并使用相应的比较器。然而,重新洗牌需要更新所有包装权重。

于 2013-02-15T11:04:10.800 回答
0
  • 您可以使用 Map 来避免重复,然后使用 Map.entrySet() 并打乱 ArrayList
于 2013-02-15T11:01:19.290 回答
0

使用最少的代码和最优雅的方式,您可以执行以下操作:

 public void testFoo() {
    Set<Integer> s = new TreeSet<Integer>();

    s.add(2);
    s.add(1);
    s.add(3);

    Collections.shuffle(Arrays.asList(s.toArray()));
}

但这不是很有效,您可以使用数组和哈希函数将元素放在数组上所需的位置,并在放置之前检查它们是否已经存在,这将在 O(n) 时间内起作用,所以它非常好,但需要更多代码和对哈希函数的一些关注。

于 2013-02-15T10:59:21.240 回答