我有这个方法为这个方法中列出的每个数组值生成一个数字(1-10)。我希望将整组数字显示为一组唯一数字。怎么做?
public static int generateNumbers(int[] lotteryNumbers) {
Random randNum = new Random();
lotteryNumbers[0] = randNum.nextInt(10);
lotteryNumbers[1] = randNum.nextInt(10);
lotteryNumbers[2] = randNum.nextInt(10);
lotteryNumbers[3] = randNum.nextInt(10);
lotteryNumbers[4] = randNum.nextInt(10);
return lotteryNumbers[4];
}
答案 0 :(得分:5)
一个简单的解决方案是生成一个包含10个数字的列表,随机播放该列表并获取前五个元素:
select date_time, value
from t1,
(select DATE_FORMAT(date_time,'%Y-%m-%d %H:00:00') h,
min(value) min, max(value) max
from t1
group by h
) t
where value in (min, max)
and DATE_FORMAT(date_time,'%Y-%m-%d %H:00:00') = h
Collections.shuffle(list)
是一种实用方法,可随机置换给定列表。
如果您使用的是Java 8,则可以写成:
List<Integer> list = new ArrayList<>(10);
for (int i = 0; i < 10; i++) {
list.add(i);
}
Collections.shuffle(list);
Integer[] lotteryNumbers = list.subList(0, 5).toArray(new Integer[10]);
答案 1 :(得分:3)
一种天真的技巧是在你想要“洗牌”的集合中随机挑选:
public static int[] generateNumbers(int exclusiveMaxValue) {
List<Integer> values = new ArrayList<>(exclusiveMaxValue);
for (int i=0 ; i<values.size() ; i++) values.add(i);
int[] result = new int[exclusiveMaxValue];
Random rd = new Random();
for (int i=0 ; i<result.length ; i++) {
result[i] = values.remove(rd.nextInt(values.size()));
}
return result;
}
但是,List.remove
通常为O(n)
,因此整个方法都是二次方法,这非常昂贵。您可以通过简单地交换元素(O(n)
执行的操作)在Collections.shuffle
中执行随机播放:
public static int[] generateNumbers(int exclusiveMaxValue) {
int[] result = new int[exclusiveMaxValue];
for (int i=0 ; i<result.length ; i++) result[i] = i;
Random rd = new Random();
for (int i=result.length - 1 ; i>=0 ; i--) {
swap(result, i, rd.nextInt(i + 1));
}
return result;
}
private static swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
答案 2 :(得分:1)
此方法生成范围为[0,N -1]的唯一数字长度N的序列。
public static int[] generateNumbers(int length) {
final int[] array = new int[length];
for (int i = 0; i < length; ++i) {
array[i] = i;
}
shuffle(array);
return array;
}
对于改组使用Fisher-Yates算法:
public static void shuffle(final int[] array) {
final Random random = new Random();
for (int i = array.length - 1; i > 0; --i) {
final int randomIdx = random.nextInt(i + 1);
final int temp = array[i];
array[i] = array[randomIdx];
array[randomIdx] = temp;
}
}
答案 3 :(得分:0)
这是一种替代方法,它使用一个集合并填充它,直到它增长到所需的大小。它会生成 numbersToDraw 不同的随机数,范围从 min 到 max (含)。它还保留了绘制数字的顺序(即 LinkedHashSet 的用途)。
private static Set<Integer> drawNumbers(int min, int max, int numbersToDraw) {
if (max < min) {
throw new IllegalArgumentException("Minimum must be less than maximum.");
}
if (max < 0 || min < 0) {
throw new IllegalArgumentException("Both range numbers must be positive.");
}
final int countOfNumbers = max - min + 1;
if (countOfNumbers < numbersToDraw) {
throw new IllegalArgumentException("Range is not big enough.");
}
final Random randomizer = new SecureRandom();
final Set<Integer> numbersDrawn = new LinkedHashSet<>();
while (numbersDrawn.size() < numbersToDraw) {
final int randomNumber = min + randomizer.nextInt(countOfNumbers);
numbersDrawn.add(randomNumber);
}
return numbersDrawn;
}
如果您不要求数字是唯一的,则可以在Java 8中使用它:
final Random randomizer = new SecureRandom();
final List<Integer> numbersDrawn = IntStream
.range(0, numbersToDraw)
.mapToObj(i -> min + randomizer.nextInt(max - min + 1))
.collect(Collectors.toList());
如果您不需要数字是唯一的,但是您想要打印它们的不同值(这是您的原始问题吗?):
final Random randomizer = new SecureRandom();
final Set<Integer> numbersDrawn = IntStream
.range(0, numbersToDraw)
.mapToObj(i -> min + randomizer.nextInt(max - min + 1))
.collect(Collectors.toSet());
还有一个替代你的具体案例:
final Set<Integer> distinctNumbers = Arrays
.stream(lotteryNumbers)
.distinct() // you can leave this as the set is distinct automatically
.boxed()
.collect(Collectors.toSet());