Java - 洗牌元素并输出特定数量

Java - Shuffling Elements and Outputting Specific Amounts

在 Java 中,有人告诉我使用这个结构来随机排列项目列表:

List<String> tasks = Arrays.asList("1","2","3","4","5","6","7","8");
Collections.shuffle(tasks);
for(String task : tasks){
    System.out.println(task); 
}

我的程序的这个解决方案的问题是我只想随机输出用户选择的一些元素(意思是,如果用户只想要五个元素而不是全部八个,我只想要其中的五个元素随机输出)。我以前从未真正使用过 lambda 或那种形式的 forloop(我对 Java 完全陌生)。我知道如何使用数组,我尝试为数组找到一个随机播放选项,但一无所获。我也试过这个:

int num = console.nextInt();
List<String> tasks = Arrays.asList("1","2","3","4","5","6","7","8");
Collections.shuffle(tasks);
for(int i = 1; i <= num; i++){
    String task = tasks;
    System.out.println(task); 
}

但显然,这种格式非常非常不正确(主要是因为我不知道这种格式是如何工作的)。我怎样才能让列表打乱顺序并只输出用户想要的元素数量?

注意:我没有 Java 8.

列表洗牌后,可以通过Iterator从头部获取元素。

int num = console.nextInt();
List<String> tasks = Arrays.asList("1","2","3","4","5","6","7","8");
Collections.shuffle(tasks);
java.util.Iterator<String> taskItr = tasks.iterator();
for(int i = 1; i <= num && taskItr.hasNext(); i++){
    String task = taskItr.next();
    System.out.println(task); 
}

(随机)打乱最初的 8 个元素,然后简单地返回该列表的一个子集会不会有什么问题?考虑以下代码:

public class ListTest {
    public static List<String> getRandomItems(int num) {
        List<String> tasks = Arrays.asList("1","2","3","4","5","6","7","8");
        Collections.shuffle(tasks);

        return tasks.subList(0, num);
    }

    public static void main(String[] args) {
        // take 5 random elements
        List<String> randomList = getRandomItems(5);
        for (String item : randomList) {
            System.out.println("Found an item: " + item);
        }
    }
}

请注意,您选择原始 8 个元素的哪个 子集并不重要,因为它们的顺序是随机的。相反,唯一重要的是您选择了正确大小的子集。

洗牌后询问用户他需要多少元素...然后使用List.sublist从0到给定的数字

示例:

public static void main(String[] args) {
    Scanner sc = new Scanner(System.in);
    List<String> tasks = Arrays.asList("1", "2", "3", "4", "5", "6", "7", "8");
    Collections.shuffle(tasks);
    System.out.println("how many do you need??");
    int userAnswer = sc.nextInt();
    List<String> res = tasks.subList(0, userAnswer);
    System.out.println("here are " + res);
}

tasksList,不能分配给 String。您需要从 tasks 获取特定的 String 以分配给 task - 或者您可以完全取消 task 因为没有必要声明一个单独的变量为了它。您的 for 循环应如下所示:

for (int i=0; i<num; i++) {
    System.out.println(tasks.get(i));
}

请注意,我还将 int i=1; i<=num; 从您的代码更改为 int i=0; i<num;。索引从 0 开始,因此通常最好从 0 开始循环,因为您将调用 tasks.get(0)tasks.get(1) 等。

给猫剥皮的另一种方法

int num = console.nextInt();
for(String task : tasks){
    System.out.println(task); 

    if (num--) <= 0) break;
}

您的第二个代码示例甚至无法编译,因为您无法将 List<String> 赋给 String。你必须使用 String task = tasks.get(i);

如果你想从列表中输出随机元素,你可以使用Random获取0到list.size()范围内的随机数并输出相应位置的元素:

List<String> tasks = Arrays.asList("1","2","3","4","5","6","7","8");
Collections.shuffle(tasks);
int num = 5;
Random random = new Random();

for(int i = 0; i < num; i++){
    System.out.println(tasks.get(random.nextInt(tasks.size())));
}

这里的问题是,由于(伪)随机生成的数字,您可能会多次输出相同的元素。解决此问题的一种方法是使用不允许重复的集合,并填充它直到列表中有足够的唯一元素:

List<String> tasks = Arrays.asList("1","2","3","4","5","6","7","8");
Collections.shuffle(tasks);
int num = 5;
Random random = new Random();
Set<String> selectedTasks = new HashSet<String>();

do {
    selectedTasks.add(tasks.get(random.nextInt(tasks.size())));
} while (selectedTasks.size() < num);

System.out.println(selectedTasks);