相关疑难解决方法(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
查看次数

递归使用Stream.flatMap()

考虑以下课程:

public class Order {

    private String id;

    private List<Order> orders = new ArrayList<>();

    @Override
    public String toString() {
        return this.id;
    }

    // getters & setters
}
Run Code Online (Sandbox Code Playgroud)

注意:重要的是要注意我无法修改此类,因为我正在从外部API中使用它.

还要考虑以下订单层次结构:

Order o1 = new Order();
o1.setId("1");
Order o11 = new Order();
o11.setId("1.1");
Order o111 = new Order();
o111.setId("1.1.1");
List<Order> o11Children = new ArrayList<>(Arrays.asList(o111));
o11.setOrders(o11Children);

Order o12 = new Order();
o12.setId("1.2");
List<Order> o1Children = new ArrayList<>(Arrays.asList(o11, o12));
o1.setOrders(o1Children);

Order o2 = new Order();
o2.setId("2");
Order o21 = new …
Run Code Online (Sandbox Code Playgroud)

java java-8 java-stream

30
推荐指数
2
解决办法
1万
查看次数

流<Stream>:flatMap与reduce

如果我执行以下代码"连接"两个流

  • 首先通过flatMapping a Stream<Stream<Integer>>
  • 然后通过减少Stream<Stream<Integer>>使用Stream.concat()

在两种情况下我都获得了相同的正确结果,但过滤操作的数量是不同的.

public class FlatMapVsReduce {
    public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);

        Predicate<Integer> predicate1 = i -> {
            System.out.println("testing first condition with " + i);
            return i == 3;
        };

        Predicate<Integer> predicate2 = i -> {
            System.out.println("testing second condition with " + i);
            return i == 7;
        };

        System.out.println("Testing with flatMap");
        Integer result1 =
            Stream.of(list.stream().filter(predicate1),
                      list.stream().filter(predicate2))
                  .flatMap(Function.identity())
                  .peek(i -> System.out.println("peeking " …
Run Code Online (Sandbox Code Playgroud)

java java-8 java-stream

10
推荐指数
1
解决办法
1654
查看次数

并行flatMap总是顺序的

假设我有这个代码:

 Collections.singletonList(10)
            .parallelStream() // .stream() - nothing changes
            .flatMap(x -> Stream.iterate(0, i -> i + 1)
                    .limit(x)
                    .parallel()
                    .peek(m -> {
                        System.out.println(Thread.currentThread().getName());
                    }))
            .collect(Collectors.toSet());
Run Code Online (Sandbox Code Playgroud)

输出是相同的线程名称,因此这里没有任何好处parallel- 我的意思是,有一个线程可以完成所有工作.

里面flatMap有这个代码:

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

我理解强制sequential属性如果"外部"流将是并行的(它们可能会阻塞),"外部"将不得不等待"flatMap"完成,反过来(因为使用相同的公共池)但为什么总是强迫吗?

这是那些在以后的版本中可能发生变化的事情之一吗?

java java-8 java-stream java-9

9
推荐指数
1
解决办法
1683
查看次数

如何将树结构转换为java中的节点流

我想在Java8节点流中转换树

这是存储可以选择的数据的节点树

public class SelectTree<D> {

  private D data;

  private boolean selected = false;

  private SelectTree<D> parent;

  private final List<SelectTree<D>> children = new ArrayList<>();

  public SelectTree(D data, SelectTree<D> parent) {
    this.data = data;
    if (parent != null) {
      this.parent = parent;
      this.parent.getChildren().add(this);
    }
  }

  public D getData() {
    return data;
  }

  public void setData(D data) {
    this.data = data;
  }

  public boolean isSelected() {
    return selected;
  }

  public void setSelected(boolean selected) {
    this.selected = selected;
  }

  public SelectTree<D> getParent() { …
Run Code Online (Sandbox Code Playgroud)

tree-traversal java-stream

8
推荐指数
2
解决办法
5536
查看次数

我如何懒洋洋地连接流?

我正在尝试实现一个在其实现中使用自身的另一个实例的流.该流有一些常量元素(使用IntStream.concat),因此只要连接流懒惰地创建非常量部分,这应该有效.我认为使用StreamSupport.intStream重载使用IntStream.concat的供应商("创建一个延迟连接的流")应该足够懒,只能在需要元素时创建第二个分裂器,但是甚至创建流(不评估)它)溢出堆栈.我如何懒洋洋地连接流?


我正试图将这个答案的流媒体素数筛选器移植到Java中.此筛使用其自身的另一个实例(ps = postponed_sieve()在Python代码中).如果我将最初的四个常量元素(yield 2; yield 3; yield 5; yield 7;)分解为它们自己的流,那么很容易将生成器实现为一个分裂器:

/**
 * based on https://stackoverflow.com/a/10733621/3614835
 */
static class PrimeSpliterator extends Spliterators.AbstractIntSpliterator {
    private static final int CHARACTERISTICS = Spliterator.DISTINCT | Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED | Spliterator.SORTED;
    private final Map<Integer, Supplier<IntStream>> sieve = new HashMap<>();
    private final PrimitiveIterator.OfInt postponedSieve = primes().iterator();
    private int p, q, c = 9;
    private Supplier<IntStream> s;
    PrimeSpliterator() {
        super(105097564 /* according to …
Run Code Online (Sandbox Code Playgroud)

java java-8 java-stream

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

如何使用 Java 8 Stream 展平嵌套的列表映射?

我有一个看起来像这样的结构:

public class Category {
    private String tag;
    private String name;
    private String description;
    private List<Item> items;
}

Run Code Online (Sandbox Code Playgroud)

Item看起来像这样

public class Item {
    private String itemTag;
    private String itemName;
    private String itemType;
    private Integer itemStatus;
    private List<Item> items;
}
Run Code Online (Sandbox Code Playgroud)

这不是最好的设计——我知道,但我无权改变那个设计。

我试图找到一种方法将这个结构展平为一个单一的Stream并找到一个Item匹配的itemTag. 使用此代码:

String tagToFind = "someTag";
List<Category> categories = getCategoriesList(); // <-- returns a list of Category
Item item = categories.stream()
                .flatMap(category -> category.getItems().stream())
                .filter(tagToFind.equals(item.getItemTag()))
                .findFirst();

Run Code Online (Sandbox Code Playgroud)

但这仅搜索项目列表的一级。如果我想更深入,我可以简单地做:

Item item = categories.stream()
                .flatMap(category …
Run Code Online (Sandbox Code Playgroud)

java recursion nested-lists java-stream

6
推荐指数
1
解决办法
3266
查看次数

为什么.flatMap()是如此低效(非懒惰)?

关于深化认识Java流spliterators的第一个问题后,这里为什么执行:约溪流另一个微妙的问题.flatMap()在Java中是如此低效(非懒惰)?

通常,流应该尽可能地保持懒惰,但.flatMap()方法不是.

例如:

stream.flatMap(this::getStreamWith10HeavyComputationElems).firstFirst() 在返回第一个繁重的计算结果之前,将消耗10个元素(10次重计算).

stream.flatMap(this::getStreamWith10HeavyComputationElems).limit(11).count() 在返回11之前将消耗20个元素(2x10重计算).

问题是为什么Java使用非懒实施?

    @Test
    void flatMap_native() throws Exception {
        AtomicInteger count = new AtomicInteger();
        Stream<Long> stream = LongStream.range(0, 5).boxed()
                .flatMap(num -> LongStream.range(0, 10).boxed()
                                    .peek(x -> count.incrementAndGet()))
                .limit(11);

        assertThat(stream).hasSize(11);
        assertThat(count).hasValue(20); //!why? - should be 11!
    }
Run Code Online (Sandbox Code Playgroud)

作为解决方法,我创建了自己的flatMap实现,但与本机调用相比,它缺乏流畅性:flatMap(stream, mapper)vs native stream.flatMap(mapper).

public static <T, R> Stream<R> flatMap(Stream<? extends T> stream, Function<? super T, ? extends Stream<? extends R>> mapper) {
    // Outside the class …
Run Code Online (Sandbox Code Playgroud)

java java-8 java-stream spliterator

5
推荐指数
0
解决办法
144
查看次数

遍历嵌套集合以找到匹配条件的第一个子子子元素

我有一个带有其他对象列表的对象,每个其他对象都有一个列表等。我需要在层次结构中找到层次结构中具有匹配某个值的属性的第一个(也是唯一的)最后一个元素。看到我现在的代码会更清楚:

    @Override
public Poste findByNumeroAndMillesime(String numero, Millesime millesime) {
    return millesime
            .getDivisions()
            .stream()
            .filter(
                    division -> division
                    .getGroupes()
                    .stream()
                    .filter(
                          groupe -> groupe
                          .getClasses()
                          .stream()
                          .filter(
                                  classe -> classe
                                  .getSousClasses()
                                  .stream()
                                  .filter(
                                          sousClasse -> sousClasse
                                          .getPostes()
                                          .stream()
                                          .filter(poste -> numero.equals(poste.getNumero()))
                                          .findFirst()
                                          .get()
                                          ))));

}
Run Code Online (Sandbox Code Playgroud)

我需要返回与作为参数传递的数字相同的 Poste。

提前致谢。

foreach java-8 java-stream

2
推荐指数
1
解决办法
778
查看次数