【问题标题】:Create a Stream using Scanner使用 Scanner 创建流
【发布时间】:2015-12-03 18:21:51
【问题描述】:

这通常是我接受来自用户的Array 的方式。我询问大小,然后循环并填充Array

Scanner scan = new Scanner(System.in);
int N = scan.nextInt();
int[] numbers = new int[N];
for (int n=0; n<N; n++){
    numbers[n] = scan.nextInt();
}

我一直在尝试学习 java 8,我注意到 Random 类现在有一个创建流的方法。现在很容易用随机数声明一个 n 大小的数组。

int[] randomNumbers = new Random().ints().limit(N).toArray();

我一直在尝试做的是创建一个数组,使用流或 lambda 表达式执行类似的操作,但用于用户输入。我尝试做的是创建一个IntStream,将值映射到Scanner#nextInt,然后创建一个数组。

int[] numbers = new IntStream().map(x -> scan.nextInt()).limit(N).toArray();

可以做的是这样的:

int[] numbers = new int[N];
Arrays.fill(numbers, 0);
numbers = Arrays.stream(numbers).map(x -> scan.nextInt()).toArray();
System.out.println(Arrays.toString(numbers));

但这仍然感觉有点多余。用一些任意数字填充数组只是为了在下一行替换它。

【问题讨论】:

  • Don’t do .ints().limit(N) Random。使用ints(N);调用toArray() 会更高效,因为它会提前知道数组大小。
  • @Holger 我没有使用Random 类。只是一个例子。不过感谢您的提醒。当我在未来的项目中使用它时会记住这一点。

标签: arrays java-8 java.util.scanner java-stream


【解决方案1】:

由于way, the current implementation handles limit(…)s,使用以下方法创建流更有效:

IntStream.range(0, N).map(i -> scan.nextInt())

这在使用toArray() 以及并行处理时会更有效,尽管使用range 操作创建了一个未使用的值。此外,这会创建一个ordered stream,其中maintains the element order

所以在使用的时候,

int[] numbers = IntStream.range(0, N).map(i -> scan.nextInt()).toArray();

这得益于提前知道数组大小。

【讨论】:

  • 范围基本上从我的示例中完成填充工作。感谢您的澄清。
  • 如果您想出一种不用范围操作创建未使用值的方法,请务必回来并在此处发布。
  • 实际上,每个解决方案都必须使用这样的值,因为它必须以某种方式计算以将结果限制为所需的数字。您只能找到隐藏它的解决方案,例如limit 的实现必须在某处有一个计数器。如果你喜欢隐藏它,你可以使用Collections.nCopies(N, scan).stream().mapToInt(Scanner::nextInt)...
  • 没有技术差异,因为流没有实现。 IntStream.range 不会“创建”数字,它只是执行指定的下游操作N 次(或在短路操作的情况下更少)传递其计数器的当前值。 IntStream.generate(…).limit(N) 会做同样的事情,但不会将计数器传递给操作(并报告不同的特征)。
  • String[] array=IntStream.range(0, N) .mapToObj(i -&gt; scan.nextLine()) .toArray(String[]::new);
【解决方案2】:

使用IntStream.generate:

int[] numbers = IntStream.generate(() -> scan.nextInt()).limit(N).toArray();

正如 cmets 中提到的,这会生成无序流。如果你想订购它,你可以使用:

IntStream.range(0, N).map(i -> scan.nextInt()).toArray();

【讨论】:

  • 没错,在您的map 中,您可以看到您没有使用x,所以您基本上需要Supplier&lt;To&gt; 而不是Function&lt;From, To&gt;
  • 咳咳,IntStream.generate 创建了一个 无序 流,这不太可能是你想要的。虽然当前的实现不会更改此用例的顺序,因为对于顺序流没有任何好处,但仍然不能保证这种行为......
  • @gonzo:好的,但在大多数情况下,开发人员不希望元素的顺序与从Scanner 中读取的顺序不同,因此对于未来的读者,即使如果你觉得可以的话。
  • @gonzo:如前所述,它在定义上是无序的(阅读the API documentation),但在这个特定的用例中你不会注意到。不过,它不能保证。见Ordering
  • @gonzo 我添加了一个订购版本:)
猜你喜欢
  • 1970-01-01
  • 2016-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多