看起来我既不能使用 ArrayList 也不能使用 Set:
Set<>
- 我可以使用一组来避免重复,但没有随机播放选项//Collections.shuffle(List<?> list)
ArrayList<>
- 我可以使用 shuffle 来随机化列表,但允许重复。
我可以使用 aSet
并将其转换为 a ArrayList
(或相反)以避免重复。或者,循环遍历集合以随机化项目。但我正在寻找更有效的东西。
看起来我既不能使用 ArrayList 也不能使用 Set:
Set<>
- 我可以使用一组来避免重复,但没有随机播放选项//Collections.shuffle(List<?> list)
ArrayList<>
- 我可以使用 shuffle 来随机化列表,但允许重复。
我可以使用 aSet
并将其转换为 a ArrayList
(或相反)以避免重复。或者,循环遍历集合以随机化项目。但我正在寻找更有效的东西。
您可以维护两个单独的集合, anArrayList
和 a HashSet
,并拒绝插入HashSet
.
如果您关心封装,请将两个集合包装在一个实现的元对象中List
,并仔细记录重复元素的插入将被拒绝,即使一般合同List
没有这样规定。
谈到这个解决方案的成本,我相信就时间而言,如果与普通的相比,成本绝对可以忽略不计ArrayList
:s 成本摊销 O(1) 上的大多数操作HashSet
,即查找和插入。另一方面,您的内存使用量将是两倍(或更多,取决于HashSet
负载因子)。
据我所知,套装没有排序,所以你显然不能洗牌。为了从列表中删除重复项,我发现:如何从 ArrayList 中删除重复的元素?.
您实际上可以使用“有序集”,例如 TreeSet。为了获得随机顺序,不要插入实际项目,而是插入具有随机重量的包装器并使用相应的比较器。然而,重新洗牌需要更新所有包装权重。
使用最少的代码和最优雅的方式,您可以执行以下操作:
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) 时间内起作用,所以它非常好,但需要更多代码和对哈希函数的一些关注。