相关疑难解决方法(0)

为什么flatMap()之后的filter()在Java流中"不完全"懒惰?

我有以下示例代码:

System.out.println(
       "Result: " +
        Stream.of(1, 2, 3)
                .filter(i -> {
                    System.out.println(i);
                    return true;
                })
                .findFirst()
                .get()
);
System.out.println("-----------");
System.out.println(
       "Result: " +
        Stream.of(1, 2, 3)
                .flatMap(i -> Stream.of(i - 1, i, i + 1))
                .flatMap(i -> Stream.of(i - 1, i, i + 1))
                .filter(i -> {
                    System.out.println(i);
                    return true;
                })
                .findFirst()
                .get()
);
Run Code Online (Sandbox Code Playgroud)

输出如下:

1
Result: 1
-----------
-1
0
1
0
1
2
1
2
3
Result: -1
Run Code Online (Sandbox Code Playgroud)

从这里我看到,在第一种情况下stream真的表现得懒惰 - 我们使用findFirst()所以一旦我们有第一个元素我们的过滤lambda没有被调用.然而,在使用flatMaps的第二种情况下,我们看到尽管找到满足过滤条件的第一个元素(它只是任何第一个元素,因为lambda总是返回true),流的其他内容仍然通过过滤函数被馈送.

我试图理解为什么它表现得像这样,而不是在第一个元素计算后放弃,如第一种情况.任何有用的信息将不胜感激.

java lambda java-8 java-stream

70
推荐指数
4
解决办法
6190
查看次数

在Java中,我如何有效和优雅地流式传输树节点的后代?

假设我们有一个由唯一Strings 标识的对象集合,以及一个Tree定义它们层次结构的类.该类使用Mapfrom节点(由其ID表示)到Collection其各自子节点的s来实现.

class Tree {
  private Map<String, Collection<String>> edges;

  // ...

  public Stream<String> descendants(String node) {
    // To be defined.
  }
}
Run Code Online (Sandbox Code Playgroud)

我想启用流式节点的后代.一个简单的解决方案是:

private Stream<String> children(String node) {
    return edges.getOrDefault(node, Collections.emptyList()).stream();
}

public Stream<String> descendants(String node) {
    return Stream.concat(
        Stream.of(node),
        children(node).flatMap(this::descendants)
    );
}
Run Code Online (Sandbox Code Playgroud)

在继续之前,我想对此解决方案做出以下断言.(我对这些是正确的吗?)

  1. Stream返回的descendants消耗资源(时间和内存) - 相对于树的大小 - 以与手动编码递归相同的复杂度顺序行走.特别地,表示迭代状态(Streams,Spliterators,...)的中间对象形成堆栈,因此在任何给定时间的存储器要求与树的深度具有相同的复杂度.

  2. 据我所知,只要我在执行终止操作Stream从返回descendants,根级别调用flatMap将导致所有包含Stream秒-一个用于每个(递归)呼叫descendants-被立即实现.因此,结果Stream …

java algorithm java-8 java-stream

18
推荐指数
2
解决办法
3060
查看次数

Java 8 Streams中的并行性和Flatmap

您好我在使用flatmap时有关于并行性的问题请考虑以下示例

    IntStream.of(-1, 1).parallel().flatMap(i->IntStream.range(0,1000).parallel()).forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

我是否将内部标志设置为并行是否重要?如果我离开或不离开,结果看起来非常相似.为什么代码(ReferencePipeline)会对映射进行顺序化?我对这条线感到困惑:

result.sequential().forEach(downstream);
Run Code Online (Sandbox Code Playgroud)

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8-b132/java/util/stream/ReferencePipeline.java#ReferencePipeline.flatMap%28java.util.function.Function% 29

java parallel-processing java-8 java-stream

14
推荐指数
1
解决办法
3163
查看次数

为什么ParallelStream不会在递归中使用所有commonPool的线程?

当我运行以下代码时,8 个可用线程中只有 2 个可以运行,任何人都可以解释为什么会出现这种情况吗?我怎样才能改变代码,使其能够利用所有 8 个线程?

Tree.java

package il.co.roy;

import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

public class Tree<T>
{
    private final T data;
    private final Set<Tree<T>> subTrees;

    public Tree(T data, Set<Tree<T>> subTrees)
    {
        this.data = data;
        this.subTrees = subTrees;
    }

    public Tree(T data)
    {
        this(data, new HashSet<>());
    }

    public Tree()
    {
        this(null);
    }

    public T getData()
    {
        return data;
    }

    public Set<Tree<T>> getSubTrees()
    {
        return subTrees;
    }

    @Override
    public boolean equals(Object o)
    {
        if (this == o)
            return true; …
Run Code Online (Sandbox Code Playgroud)

java multithreading java-8 java-stream java-17

7
推荐指数
1
解决办法
198
查看次数

使用 ForkJoin 和 Streams 构建自适应网格细化

我想在 3D 中构建自适应网格细化。

基本原理如下:

我有一组具有唯一单元 ID 的单元。我测试每个单元,看看它是否需要改进。

  • 如果需要细化,则创建 8 个新的子单元格并将它们添加到单元格列表中以检查细化。
  • 否则,这是一个叶节点,我将其添加到我的叶节点列表中。

我想使用 ForkJoin 框架和 Java 8 流来实现它。我读了这篇文章,但我不知道如何将其应用到我的案例中。

现在,我想到的是:

public class ForkJoinAttempt {
    private final double[] cellIds;

    public ForkJoinAttempt(double[] cellIds) {
        this.cellIds = cellIds;
    }

    public void refineGrid() {
        ForkJoinPool pool = ForkJoinPool.commonPool();
        double[] result = pool.invoke(new RefineTask(100));
    }

    private class RefineTask extends RecursiveTask<double[]> {
        final double cellId;

        private RefineTask(double cellId) {
            this.cellId = cellId;
        }

        @Override
        protected double[] compute() {
            return ForkJoinTask.invokeAll(createSubtasks())
                    .stream()
                    .map(ForkJoinTask::join)
                    .reduce(new double[0], new Concat()); …
Run Code Online (Sandbox Code Playgroud)

java concurrency fork-join java-stream

5
推荐指数
1
解决办法
166
查看次数

使流平行于 flatMap 的结果

考虑以下简单代码:

Stream.of(1)
  .flatMap(x -> IntStream.range(0, 1024).boxed())
  .parallel() // Moving this before flatMap has the same effect because it's just a property of the entire stream
  .forEach(x -> {
     System.out.println("Thread: " + Thread.currentThread().getName());
  });
Run Code Online (Sandbox Code Playgroud)

很长一段时间,我认为即使在flatMap. 但是上面的代码打印了所有的“Thread:main”,证明我的想法是错误的。

一种使其并行的简单方法flatMap是收集然后再次流式传输:

Stream.of(1)
  .flatMap(x -> IntStream.range(0, 1024).boxed())
  .parallel() // Moving this before flatMap has the same effect because it's just a property of the entire stream
  .collect(Collectors.toList())
  .parallelStream()
  .forEach(x -> {
     System.out.println("Thread: " + Thread.currentThread().getName());
  });
Run Code Online (Sandbox Code Playgroud)

我想知道是否有更好的方法,以及flatMap仅在调用之前并行化流的设计选择,而不是在调用之后并行化。

========关于问题的更多说明========

从一些答案来看,我的问题似乎没有完全表达出来。正如@Andreas 所说,如果我从 …

java parallel-processing java-stream

5
推荐指数
1
解决办法
293
查看次数