如果您有一个Array并且想要使用Java8 forEach()方法,那么哪种方法更好或更有效:
Arrays.asList(new String[]{"hallo","hi"}).forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)
要么
Arrays.stream(new String[]{"hallo","hi"}).forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)
差异是显着的还是有更好的解决方案来解决这个问题?
假设我有两个int[]数组input1和input2.我想从第一个中取正数,从第二个中取出不同的数字,将它们合并在一起,排序并存储到结果数组中.这可以使用流执行:
int[] result = IntStream.concat(Arrays.stream(input1).filter(x -> x > 0),
Arrays.stream(input2).distinct()).sorted().toArray();
Run Code Online (Sandbox Code Playgroud)
我想加快任务,所以我考虑使流并行.通常这只意味着我可以.parallel()在流构造和终端操作之间插入任何地方,结果将是相同的.IntDream.concat的JavaDoc 表示如果任何输入流是并行的,则生成的流将是并行的.所以,我认为做parallel()任何input1流或input2流或级联的流将产生相同的结果.
实际上我错了:如果我添加.parallel()到结果流,似乎输入流保持顺序.此外,我可以将输入流(它们中的任何一个或两者)标记为.parallel(),然后将结果流转换为.sequential(),但输入保持平行.所以实际上有8种可能性:input1,input2和连接流都可以是并行的:
int[] sss = IntStream.concat(Arrays.stream(input1).filter(x -> x > 0),
Arrays.stream(input2).distinct()).sorted().toArray();
int[] ssp = IntStream.concat(Arrays.stream(input1).filter(x -> x > 0),
Arrays.stream(input2).distinct()).parallel().sorted().toArray();
int[] sps = IntStream.concat(Arrays.stream(input1).filter(x -> x > 0),
Arrays.stream(input2).parallel().distinct()).sequential().sorted().toArray();
int[] spp = IntStream.concat(Arrays.stream(input1).filter(x -> x > 0),
Arrays.stream(input2).parallel().distinct()).sorted().toArray();
int[] pss = IntStream.concat(Arrays.stream(input1).parallel().filter(x -> x > 0),
Arrays.stream(input2).distinct()).sequential().sorted().toArray(); …Run Code Online (Sandbox Code Playgroud) 将流转换为滑动窗口的推荐方法是什么?
例如,在Ruby中你可以使用each_cons:
irb(main):020:0> [1,2,3,4].each_cons(2) { |x| puts x.inspect }
[1, 2]
[2, 3]
[3, 4]
=> nil
irb(main):021:0> [1,2,3,4].each_cons(3) { |x| puts x.inspect }
[1, 2, 3]
[2, 3, 4]
=> nil
Run Code Online (Sandbox Code Playgroud)
在Guava中,我发现只有Iterators#partition,它是相关的但没有滑动窗口:
final Iterator<List<Integer>> partition =
Iterators.partition(IntStream.range(1, 5).iterator(), 3);
partition.forEachRemaining(System.out::println);
-->
[1, 2, 3]
[4]
Run Code Online (Sandbox Code Playgroud) 我有Map<A, Map<B, C>>,我想Map<B, List<C>>使用Java Streams 从中获取.
我尝试按如下方式进行:
public <A, B, C> Map<B, List<C>> groupsByInnerKey(Map<A, Map<B, C>> input) {
return input.values()
.stream()
.flatMap(it -> it.entrySet().stream())
.collect(Collectors.groupingBy(Map.Entry::getKey));
}
Run Code Online (Sandbox Code Playgroud)
我期待的是:
flatMap给人Stream的Map.Entry<B, C>collect(Collectors.groupingBy(...))获取应用于Map.Entry<B, C>和返回的函数B,从而收集C到的值List<C>.但它没有编译,字面意思:
无法从静态上下文引用非静态方法
在Map.Entry::getKey最后一行.
有人可以解释什么是错的或什么是实现我想要的正确方法?
我正在寻找一种简洁的方法来过滤掉特定索引中List中的项目.我的示例输入如下所示:
List<Double> originalList = Arrays.asList(0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0);
List<Integer> filterIndexes = Arrays.asList(2, 4, 6, 8);
Run Code Online (Sandbox Code Playgroud)
我想筛选出的索引项2,4,6,8.我有一个for循环跳过与索引匹配的项目,但我希望有一种简单的方法可以使用流来完成.最终结果如下:
List<Double> filteredList = Arrays.asList(0.0, 1.0, 3.0, 5.0, 7.0, 9.0, 10.0);
Run Code Online (Sandbox Code Playgroud) 考虑这些类和累积函数,它们代表了我原始上下文的简化(但是再现了同样的问题):
abstract static class Foo {
abstract int getK();
}
static class Bar extends Foo {
int k;
Bar(int k) { this.k = k; }
int getK() { return this.k; }
}
private static Foo combined(Foo a1, Foo a2) {
return new Bar(a1.getK() + a2.getK());
}
Run Code Online (Sandbox Code Playgroud)
我试图通过依赖单独的函数来执行项目的累积(最初的数据索引报告)combined,该函数直接处理类型的元素Foo.
Foo outcome = Stream.of(1,2,3,4,5)
.map(Bar::new)
.reduce((a,b) -> combined(a, b))
.get();
Run Code Online (Sandbox Code Playgroud)
事实证明,此代码导致编译错误(OpenJDK"1.8.0_92"):"lambda表达式中的错误返回类型:Foo无法转换为Bar".编译器坚持尝试使用Bar累积元素来减少流,即使Foo累积函数的参数和返回类型都有公共类型.
我还发现,只要我明确地将流映射到Foos 流中,我仍然可以采用这种方法:
Foo outcome = Stream.of(1,2,3,4,5)
.<Foo>map(Bar::new)
.reduce((a,b) -> combined(a, …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用以下签名实现一个方法:
public static <A,B> Pair<Stream<A>, Stream<B>> flatten(Iterator<Pair<Stream<A>, Stream<B>>> iterator);
Run Code Online (Sandbox Code Playgroud)
方法的目标是将每个流类型展平为单个流并将输出包装成一对.我只有一个迭代器(不是Iterable),我不能改变方法签名,所以我必须在一次迭代中执行展平.
我目前最好的实施是
public static <A,B> Pair<Stream<A>, Stream<B>> flatten(Iterator<Pair<Stream<A>, Stream<B>> iterator) {
Stream<A> aStream = Stream.empty();
Stream<B> bStream = Stream.empty();
while(iterator.hasNext()) {
Pair<Stream<A>, Stream<B>> elm = iterator.next();
aStream = Stream.concat(aStream, elm.first);
bStream = Stream.concat(bStream, elm.second);
}
return Pair.of(aStream, bStream);
}
Run Code Online (Sandbox Code Playgroud)
虽然这在技术上是正确的,但我对此并不十分满意,原因有两个:
感觉Stream#flatMap应该适合这里(在使用Guava的Streams.stream(Iterator)将输入Iterator转换为Stream之后,但由于中间的Pair类型,它似乎不起作用.
另外一个要求是任何迭代器/流可能非常大(例如,输入可能包含从一对极大的流到一个项目流中的许多流的任何地方),因此理想情况下,解决方案不应包含收集结果. - 记忆收藏.
我对中间阶段的顺序的状态的问题-从施加到一个阶段的操作的所有输入流(项目)或是所有级/操作施加到各流项目?
我知道这个问题可能不容易理解,所以我举一个例子.在以下流处理中:
List<String> strings = Arrays.asList("Are Java streams intermediate stages sequential?".split(" "));
strings.stream()
.filter(word -> word.length() > 4)
.peek(word -> System.out.println("f: " + word))
.map(word -> word.length())
.peek(length -> System.out.println("m: " + length))
.forEach(length -> System.out.println("-> " + length + "\n"));
Run Code Online (Sandbox Code Playgroud)
我对这段代码的期望是它会输出:
f: streams
f: intermediate
f: stages
f: sequential?
m: 7
m: 12
m: 6
m: 11
-> 7
-> 12
-> 6
-> 11
Run Code Online (Sandbox Code Playgroud)
相反,输出是:
f: streams
m: 7
-> 7
f: intermediate
m: …Run Code Online (Sandbox Code Playgroud) 任何人都可以指向官方Java文档,该文档描述了Stream将为每个元素调用每个"非干扰和无状态"中间操作的次数.
例如:
Arrays.asList("1", "2", "3", "4").stream()
.filter(s -> check(s))
.forEach(s -> System.out.println(s));
public boolean check(Object o) {
return true;
}
Run Code Online (Sandbox Code Playgroud)
以上目前将调用check方法4次.
是否有可能在JDK的当前版本或未来版本中,该check方法的执行次数多于或少于从List或任何其他标准Java API创建的流中的元素数量?
我试图从两个潜在的无限流中召唤一个笛卡尔积,然后我通过limit().
到目前为止,这(大约)是我的策略:
@Test
void flatMapIsLazy() {
Stream.of("a", "b", "c")
.flatMap(s -> Stream.of("x", "y")
.flatMap(sd -> IntStream.rangeClosed(0, Integer.MAX_VALUE)
.mapToObj(sd::repeat)))
.map(s -> s + "u")
.limit(20)
.forEach(System.out::println);
}
Run Code Online (Sandbox Code Playgroud)
这不起作用。
显然,我的第二个流在第一次在管道上使用时就被当场进行了最终评估。它不会产生我可以按照自己的节奏使用的惰性流。
我认为.forEach这段代码中的原因ReferencePipeline#flatMap是:
@Override
public void accept(P_OUT u) {
try (Stream<? extends R> result = mapper.apply(u)) {
if (result != null) {
if (!cancellationRequestedCalled) {
result.sequential().forEach(downstream);
}
else {
var s = result.sequential().spliterator();
do { } while (!downstream.cancellationRequested() && s.tryAdvance(downstream));
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我希望上面的代码返回 20 …