【问题标题】:Java - Create an IntStream with a given range, then randomise each element using a map functionJava - 创建具有给定范围的 IntStream,然后使用映射函数随机化每个元素
【发布时间】:2018-01-10 17:25:08
【问题描述】:

所以我创建了一个 IntStream,我给它的范围是 1 - 9。我希望能够使用 map 函数来获取给定范围 (1-9) 中的每个元素并随机化每个元素。

基本上我想在每次运行程序时以不同的顺序流式传输数字 1 - 9。 (我对其他想法持开放态度,但必须使用流)。

我听说过使用 Java 的 Random 类,但我不确定如何在每个元素的映射上实现它。

我试过这样做,但有错误:

 IntStream.range(1, 9).map(x -> x = new Random()).forEach(x -> System.out.println(x));

任何帮助将不胜感激。

【问题讨论】:

  • “基本上我想在每次运行程序时以不同的顺序流式传输数字 1 - 9。(我对其他想法持开放态度,但它必须使用流)”直言不讳: 如果这是你的目标,放弃吧。流对于这个任务来说不是一个有用的抽象,并且很可能是有问题的。当然,如果这不是您的目标,那么您也许可以做点什么。
  • Random#ints(x, y)?
  • x -> x = new Random() 这不是你认为的那样。 x 是一个整数变量,您正在尝试将 Random 类型的对象分配给它。
  • @GR412 不会的。最好的办法是有一个中间列表:List<Integer> list = IntStream.rangeClosed(1, 9).boxed().collect(toList()); Collections.shuffle(list); return list.stream();
  • 定义“进一步的问题”。 (您可以将明确的Random 传递给Collections.shuffle。)但说真的,Collections.shuffle 是解决这个问题的正确方法。

标签: java random java-8 java-stream


【解决方案1】:

使用Random.ints也可以这样做:

new Random().ints(1,10)
        .distinct()
        .limit(9)
        .forEach(System.out::println);

输出:

9 8 4 2 6 3 5 7 1

编辑

如果您需要带有值的Stream,请执行以下操作:

Stream<Integer> randomInts = new Random().ints(1, 10)
        .distinct()
        .limit(9)
        .boxed();

如果您需要带有值的List,请执行以下操作:

List<Integer> randomInts = new Random().ints(1, 10)
        .distinct()
        .limit(9)
        .boxed()
        .collect(Collectors.toList());

【讨论】:

  • @DodgyCodeException:实际上,我们知道Random 并不是真正随机的,而是使用规范中固定的算法。我们可以放心地假设它最终总是会遇到 1 到 10 之间的所有值。
  • @JuanCarlosMendoza 不,如果 Random真正随机的,那么序列 5 5 5 5 5 5 5 5 5 5 与 8 4 7 5 6 的可能性相同9 3 5 1 2(或者你掷骰子给你的任何东西)。 可能使用真正的随机数来获得相同数字(或相同数字集)的极长序列。然而,正如 Holger 正确指出的那样,Random 并不是真正随机的,我们知道我们可以依靠它生成从 1 到 9 的所有数字。
  • @GR412 只需在.limit(9) 之后添加.boxed(),您将拥有Stream&lt;Integer&gt;
  • @GR412 自定义列表有何重要意义? List&lt;Integer&gt; list = new Random().ints(1, 10).distinct().limit(9).boxed().collect(Collectors.toList()); 有什么问题?
  • 是的,但是static 方法是创建该列表的唯一方法吗?通常,列表实现有一个“复制构造函数”,接受另一个列表,所以你可以使用List&lt;Integer&gt; list = new Random().ints(1, 10).distinct().limit(9).boxed().collect(Collectors.collectingAndThen( Collectors.toList(), CustomList::new)​);
【解决方案2】:

流确实不适合这项工作。就像,真的 真的

更好的方法是使用Collections.shuffle

// you can replace this with however you want to populate your array. 
// You can do a for loop that loops from 1 to 9 and add each number.
ArrayList<Integer> list = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9));
Collections.shuffle(list);
// now "list" is in a random order

编辑:

现在我知道您有一个自定义列表,这是另一种方法。编写两个方法将您的自定义列表转换​​为普通的ArrayList,反之亦然。将您的自定义列表转换​​为 ArrayList,进行随机播放,然后将其转换回来。

只是为了好玩,Stream,当并行时,可以按随机顺序生产东西,但不是真的。

我运行了这个代码 10 次:

IntStream.range(1, 10).parallel().forEach(System.out::print);

这是输出:

347195628
342179856
832497165
328194657
326479581
341287956
873629145
837429156
652378914
632814579

【讨论】:

  • 虽然生成 10 个随机数,但我在值 1-9 之后,但每次排序不同。我应该说得更清楚一点,但这确实是我每次都希望随机的顺序。
  • 你到底是什么意思? 1-9 10个数字。 @GR412
  • 我基本上想要值 1,2,3,4,5,6,7,8,9 但随机排序,比如 6,5,3,1,2,4,8, 9,7.
  • @GR412 是的,这正是Collection.shuffle 所做的。你不认为它会那样做吗?你觉得它有什么作用?
  • @DodgyCodeException 你甚至不需要ArrayListArrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9) 返回的List 已经足够了。将其洗牌并从中构造不可变列表;如果只有那个工厂方法接受流,list.stream() 会起作用。
【解决方案3】:
public static void main(String[] args) {
    Random random = new Random(); 
    //infinite stream of integers between 1(inclusive) and 10(exclusive)
    IntStream intStream = random.ints(1, 10);
    //from the infinite stream get a stream of 9 random and distinct integers and print them        
    intStream.distinct().limit(9).forEach(System.out::println);
}

【讨论】:

  • 这正是我正在寻找的,但是否可以将它从 IntStream 更改为只是一个 Stream?因为我有一种方法可以将流转换为列表,但它似乎不接受 IntStreams 作为参数。
猜你喜欢
  • 2018-06-20
  • 2018-10-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-20
  • 1970-01-01
相关资源
最近更新 更多