【发布时间】:2015-09-07 13:25:10
【问题描述】:
我想生成一对随机数而不重复这对。我如何在 java 中实现它?
【问题讨论】:
-
你的意思是这2个随机数不应该相等吗?
-
请分享到目前为止你尝试过的任何东西。
-
你想这样做多久?对重复也意味着排序?也请分享你的尝试
我想生成一对随机数而不重复这对。我如何在 java 中实现它?
【问题讨论】:
Random r = new Random();
int x, y;
do {
x = r.nextInt();
y = r.nextInt();
} while (x == y);
【讨论】:
我们需要跟踪已经生成的对。以下代码应该这样做:
Random random = new Random();
Map<Integer, Integer> generated = new HashMap<Integer, Integer>();
int x,y;
do{
x = random.nextInt();
y = random.nextInt();
if(!generated.containsKey(x) || generated.get(x) != y){
generated.put(x, y);
break;
}
}while(true);
【讨论】:
如果你需要2个以上的数字,这种方法可能更有效:
List<Integer> integers = IntStream.range(1, 10)
.boxed()
.collect(Collectors.toList());
Collections.shuffle(integers);
System.out.println(integers.get(0));
System.out.println(integers.get(1));
【讨论】:
据我了解您的问题,您希望生成随机数字对而不重复它们。为此,我们首先需要一个保存值的类,因为它是一对数字,我称之为元组。
public class Tuple {
private Integer first;
private Integer second;
public Tuple(int first, int second) {
this.first = first;
this.second = second;
}
public int getFirst() {
return first;
}
public int getSecond() {
return second;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Tuple tuple = (Tuple) o;
return first.equals(tuple.first) && second.equals(tuple.second);
}
@Override
public int hashCode() {
int result = first.hashCode();
result = 31 * result + second.hashCode();
return result;
}
}
然后我们需要一个生成器类来保存可能出现在一对中的最高整数。请注意,此数字限制了可能的对数,因为您可以将包含 1...n 个数字的元组作为第一个数字,并且对于它们中的每一个,再将 1...n 个数字作为第二个,您最多可以返回 n*n 个元组!
public class RandomTuples {
private final int highestInt;
private final Set<Tuple> usedTuples = new HashSet<>();
public RandomTuples(int highestInt) {
this.highestInt = highestInt;
}
public Tuple nextTuple() {
if (usedTuples.size() >= highestInt*highestInt) {
throw new RuntimeException("All possible tuples were used. " +
"Use a higher param when instantiating RandomTuples for more!");
}
Random rnd = new Random();
Tuple tuple = Stream
.generate(() -> new Tuple(rnd.nextInt(highestInt), rnd.nextInt(highestInt)))
.filter(filterTuple -> !usedTuples.contains(filterTuple))
.limit(1).findFirst().get();
usedTuples.add(tuple);
return tuple;
}
}
这里的异常至关重要,否则流将陷入死锁。它将 generate 新元组尝试获取至少一个匹配条目 (limit(1)),而 filter 将删除此条目,从而创建一个无限循环...
然后你必须实例化 RandomTouples 类并调用生成方法来获取一个新的元组。当使用大量数字时,这可能会以非常糟糕的性能运行,因为它必须尝试可能的组合,直到找到尚未使用的组合。
public class RandomTuplesExample {
public static void main(String[] args) {
RandomTuples randomTuples = new RandomTuples(10);
for (int i = 0; i < 100; i++) {
Tuple tuple = randomTuples.nextTuple();
System.out.println("(" + tuple.getFirst() + ", " + tuple.getSecond() + ")");
}
}
}
【讨论】: