gpt4 book ai didi

java - 递归使用 Stream.flatMap()

转载 作者:IT老高 更新时间:2023-10-28 21:06:24 26 4
gpt4 key购买 nike

考虑以下类:

public class Order {

private String id;

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

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

// getters & setters
}

注意:请务必注意,我无法修改此类,因为我从外部 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 Order();
o21.setId("2.1");
Order o22 = new Order();
o22.setId("2.2");
Order o23 = new Order();
o23.setId("2.3");
List<Order> o2Children = new ArrayList<>(Arrays.asList(o21, o22, o23));
o2.setOrders(o2Children);

List<Order> orders = new ArrayList<>(Arrays.asList(o1, o2));

可以用这种方式直观地表示:

1
1.1
1.1.1
1.2
2
2.1
2.2
2.3

现在,我想将这个订单层次结构扁平化为一个List,这样我就可以得到以下信息:

[1, 1.1, 1.1.1, 1.2, 2, 2.1, 2.2, 2.3]

我已经设法通过递归地使用 flatMap() (以及一个辅助类)来做到这一点,如下所示:

List<Order> flattened = orders.stream()
.flatMap(Helper::flatten)
.collect(Collectors.toList());

这是辅助类:

public final class Helper {

private Helper() {
}

public static Stream<Order> flatten(Order order) {
return Stream.concat(
Stream.of(order),
order.getOrders().stream().flatMap(Helper::flatten)); // recursion here
}
}

下面一行:

System.out.println(flattened);

产生以下输出:

[1, 1.1, 1.1.1, 1.2, 2, 2.1, 2.2, 2.3]

到目前为止一切顺利。结果绝对正确。

但是,after reading this question ,我对在递归方法中使用 flatMap() 有一些担忧。特别是,我想知道流是如何扩展的(如果这是术语)。所以我修改了 Helper 类并使用 peek(System.out::println) 来检查这个:

public static final class Helper {

private Helper() {
}

public static Stream<Order> flatten(Order order) {
return Stream.concat(
Stream.of(order),
order.getOrders().stream().flatMap(Helper::flatten))
.peek(System.out::println);
}
}

输出是:

1
1.1
1.1
1.1.1
1.1.1
1.1.1
1.2
1.2
2
2.1
2.1
2.2
2.2
2.3
2.3

我不确定这是否是应该打印的输出。

所以,我想知道是否可以让中间流包含重复的元素。此外,这种方法的优缺点是什么?毕竟,以这种方式使用 flatMap() 是否正确?有没有更好的方法来达到同样的效果?

最佳答案

嗯,我在一个通用的 Tree 类中使用了相同的模式,并且对它没有任何错误的感觉。唯一的区别是,Tree 类本身提供了一个 children()allDescendants() 方法,它们都返回一个 Stream 和后者建立在前者之上。这与 “Should I return a Collection or a Stream?” 有关和 “Naming java methods that return streams” .

Stream 的角度来看,flatMap 到不同类型的子级(即遍历属性时)和 flatMap< 之间没有区别 给同类型的 child 。如果返回的流再次包含相同的元素也没有问题,因为流的元素之间没有关系。原则上,您可以使用 flatMap 作为 filter 操作,使用模式 flatMap(x -> condition? Stream.of(x): Stream.empty( ))。也可以使用它来复制 this answer 中的元素。 .

关于java - 递归使用 Stream.flatMap(),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32656888/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com