这是我的解决方案:
List<String> st = Arrays.asList("aaaa","bbbb","cccc");
System.err.println(st.stream().sorted((o1, o2) -> RandomUtils.nextInt(0, 2)-1).findFirst().get());
当元素的类型未知时,与前面的答案相比,更加一般化:
public static <T> Comparator<T> shuffle() {
final Map<Object, UUID> uniqueIds = new IdentityHashMap<>();
return Comparator.comparing(e -> uniqueIds.computeIfAbsent(e, k -> UUID.randomUUID()));
}
也可以在流中使用:
list.stream().sorted(Streams.shuffle()).collect(Collectors.toList())
可能会以某种方式发生冲突,因此可以使用 UUID
的 HashSet
进行扩展以检查这种情况
在不破坏合同的情况下实现真正的“洗牌比较器”是不可能的。比较
器合约的一个基本方面是结果是可重现的,因此必须固定特定比较器
实例的顺序。
当然,您可以使用混洗操作预先初始化该固定顺序,并创建一个比较器来准确建立该顺序。例如
List<ElementType> ordering=new ArrayList<>(list);
Collections.shuffle(ordering);
list.sort(Comparator.comparingInt(ordering::indexOf));
尽管这有点没有意义。很明显,这个比较器不能用于包含不在排序
列表中的元素的集合。
或者,您可以使用首先没有排序的值的稳定属性作为排序标准,例如哈希代码。这可以通过稳定但可随机化的转换来增强,例如
public static Comparator<String> randomOrder() {
ThreadLocalRandom r = ThreadLocalRandom.current();
int x = r.nextInt(), y = r.nextInt(), z = r.nextInt();
boolean b = r.nextBoolean();
return Comparator.comparingInt((String s) -> Integer.reverse((s.hashCode()&x)^y))
.thenComparingInt(s -> s.length()^z)
.thenComparing(b? Comparator.naturalOrder(): Comparator.reverseOrder());
}
List<String> list=Arrays.asList("hello", "now", "shuffle", "this", "!");
list.sort(randomOrder());
System.out.println(list);
list.sort(randomOrder());
System.out.println(list);
关键点是,每个Comparator
实例代表一个随机选择但固定的排序,我们创建一个新的Comparator
实例来请求不同的排序。因此,没有Comparator
违反合同。
请注意,这个<code>比较器</code>看起来有点复杂,因为它必须考虑可能的哈希冲突。它将使用<code>length</code>属性(也是随机化的),然后对于具有相同哈希码和长度的<code>String</code>,它将简单地返回到自然或反向顺序,这不太可能被注意到,因为它只影响这些不常见对的关系。
如果为没有冲突的值(例如整数
实例)或覆盖定义相等的值的所有属性(例如,点的 x
和 y
)创建这样的比较器,则
比较器看起来会简单得多。
问题内容: 有没有什么方法可以模拟Collections.shuffle的行为,而比较器不容易受到排序算法实现的影响,从而确保结果安全? 我的意思是不违反可比合同等。 问题答案: 不打破合同就不可能实现真正的“改组比较器”。合同的一个基本方面是,结果是可 重现的, 因此必须确定特定实例的顺序。 当然,您可以使用混洗操作预先初始化该固定顺序,并创建一个比较器来精确地建立此顺序。例如 虽然没有意义。显
配置 UserAgent 列表 @app.beans: [ 'UserAgentManager' => [ 'list' => [ // 这里可以放想要用的 UserAgent 列表 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36
每次产生一个随机数。 用法 Your browser does not support the video tag. 案例:掷骰子 功能:设置随机数范围1-6,每按一下按钮,产生一个随机数 工作原理 当输入由no变为yes时,一个随机数将会被传送到输出。你可以通过配置改变随机数的范围 例如:一个随机变色的灯
问题内容: 当他每次运行程序时都不断获得相同的数字时,我试图向Java解释随机数生成器。我为同一件事创建了自己的简单版本,每次运行该程序时,我也得到了与他得到的确切数字相同的数字。 我究竟做错了什么? 100个数字中的最后五个数字是: 问题答案: 您已经为随机数生成器提供了恒定的值。它是确定性的,因此每次运行都会生成相同的值。 我不确定您为什么选择使用作为种子,但是种子值与生成的值范围无关(这是由
一个简单的新手问题,奇怪的是我一直没能找到解决方法。
给定一个随机数生成器random(7),它可以以相等的概率生成数字1,2,3,4,5,6,7(即每个数字出现的概率为1/7)。现在我们要设计一个随机数(5),它能以相等的概率(1/5)生成1,2,3,4,5。 有一种方法:每次我们随机运行(7),只有当它生成1-5时才返回。如果是6或7,再运行一次,直到它是1-5。 我有点困惑。第一个问题是: 如何用数学方法证明每个数字发生的概率是1/5?例如,假