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