Stream.flatMap() 的递归使用
请考虑以下类:
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]
目前为止,一切都好。结果是绝对正确的。
但是,在阅读了这个问题之后,我对递归方法中如何使用有一些担忧。特别是,我想知道流是如何扩展的(如果这是术语的话)。所以我修改了这个类,并用来检查这个: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()