如何从哈希图中打印多个元素的随机唯一值



我正在开发一个程序,其中有一个任务列表,每个任务都有预测的持续时间。例如:{task: laundry, time: 1000}, {task: cooking, time: 2000}, {task: cleaning, time: 3000}等。我想在将任务打印到控制台的同时,选择多个项目并增加一个整数变量。我的方法是首先制作一个HashMap,任务是键,时间是值。然后,我将时间值放在ArrayList中,迭代所需的次数,并递增时间变量。

我遇到的问题是我需要唯一的数字,所以我选择使用哈希集来只跟踪唯一的值。然而,我不能用这种方法打印任务,如果我迭代一定次数,如果键重复,我可能无法在集合中获得足够的值。

这是我这部分的代码。

int time = 0; 
Random rand = new Random();
ArrayList<Integer> eta = new ArrayList<Integer>(tasks.values());
HashSet <Integer> set = new HashSet<>();

for (int i = 0; i<=5; i++) {
int randomIndex = rand.nextInt(eta.size());
int tim = eta.get(randomIndex);
set.add(tim);
}
Iterator<Integer> it = set.iterator();
while(it.hasNext()){
System.out.println(it.next());
time += it.next();
}
return time;}

我将时间值打印到控制台,在它因NoSuchElementException错误而崩溃之前得到了3个值。有没有办法解决这个问题,或者有没有更好的方法来解决这个问题。最好是我可以随机选择5个值,打印任务并增加时间变量。

谢谢。

两个列表

从您的方法开始,您还可以在List中添加键(任务名称(,以便通过随机索引检索它们。

一旦你得到了一个索引,就从两个列表中删除相应的元素,这样下次你就会找到另一个有效的元素,而不是重复的元素。

int time = 0;
Random rand = new Random();
List<Integer> eta = new ArrayList<>();
List<String> taskNames = new ArrayList<>();

tasks.forEach((k,v) -> {
eta.add(v);
taskNames.add(k);
});
for (int i = 0; i < 5; i++) {
int randomIndex = rand.nextInt(eta.size());
Integer taskTime = eta.remove(randomIndex);
String taskName = taskNames.remove(randomIndex); 
System.out.println(taskName  + ": " + taskTime);
time += taskTime;
}
System.out.println("Total time: " + time);

一个列表

实际上,您不需要值列表(eta(,因为您可以使用键有效地从HashMap中检索值。

所以你实际上只需要密钥列表:

int time = 0;
Random rand = new Random();
List<String> taskNames = new ArrayList<>(tasks.keySet());
for (int i = 0; i < 5; i++) {
int randomIndex = rand.nextInt(taskNames.size());
String taskName = taskNames.remove(randomIndex);
Integer taskTime = tasks.get(taskName);
System.out.println(taskName  + ": " + taskTime);
time += taskTime;
}
System.out.println("Total time: " + time);

无序播放

您可以用Collections.shuffle打乱列表,并考虑前5个元素:,而不是找到随机索引

int time = 0;
List<String> taskNames = new ArrayList<>(tasks.keySet());
Collections.shuffle(taskNames);
for (int i = 0; i < 5; i++) {
String taskName = taskNames.get(i);
Integer taskTime = tasks.get(taskName);
System.out.println(taskName  + ": " + taskTime);
time += taskTime;
}
System.out.println("Total time: " + time);

无序播放+流

您可以使用流式API来获取总时间。

要打印任务名称,您必须使用peek,它应该仅用于调试目的,但在您的情况下似乎是合适的:

List<String> taskNames = new ArrayList<>(tasks.keySet());
Collections.shuffle(taskNames);
int time = taskNames.stream()
.limit(5)
.peek(System.out::println)
.mapToInt(tasks::get)
.sum();
System.out.println("Total time: " + time);

随机流

代替Collections.shuffle,我们可以使用流式API生成随机索引:

List<String> taskNames = new ArrayList<>(tasks.keySet());
int time = new Random().ints(0, taskNames.size())
.distinct()
.limit(5)
.mapToObj(taskNames::get)
.peek(System.out::println)
.mapToInt(tasks::get)
.sum();
System.out.println("Total time: " + time);

NoSuchElementException的原因是您在迭代器的末尾运行。

while(it.hasNext()){
System.out.println(it.next());
time += it.next();
}

每次调用"next"时,都会推进迭代器,因此需要消耗两个元素。给定奇数个元素,循环的最后一次hasNext((为true,读取最后一个元素(在println调用中调用next(((,然后再次调用next(,结果失败。

在hasNext((之后调用next((一次。

while(it.hasNext()){
Integer n = it.next();
System.out.println(n);
time += n;
}

最新更新