使用 Streams 根据 Java 中最内层列表中的元素从包含其他对象的 3 维对象列表中过滤
Filtering from a 3-dimensional List of Objects containing other objects based on the elements from innermost List in Java using Streams
假设我们有一个 3 维对象列表。
class Custom {
int id;
List<String> list;
Custom(id, list) { // Constructor }
// Getters and Setters
}
class CustomContainer {
int id;
List<Custom> list;
CustomContainer(id, list) { // Constructor }
// Getters and Setters
}
var l1 = List.of("abc", "def", "acd");
var l2 = List.of("bed", "fed", "aed");
var c1 = new Custom(1, l1);
var c2 = new Custom(2, l2);
var l3 = List.of(c1, c2);
var l4 = List.of(c2);
var cc1 = new CustomContainer(3, l3)
var cc2 = new CustomContainer(4, l4)
var containers = List.of(cc1, cc2);
说我想过滤“容器”,这样我想从最里面的列表中删除以“a”开头的所有元素。
因此,输出应该是(考虑到 toString() 仅打印列表中的字符串):
[[["def"],["bed", "fed"]], [["bed", "fed"]]]
如何在 Java 中使用 Streams 获取此内容?
由于您需要处理最内层的集合,但又想收集最外层的元素,因此您需要处理 CustomContainer
的 List
,然后为每个元素的列表调用 foreach
(收集方法不是流方法)和removeIf
。
List<CustomContainer> res = containers.stream()
.peek(container -> container.getList().forEach(custom -> custom.getList().removeIf(str -> str.startsWith("a"))))
.collect(Collectors.toList());
在测试您的代码时,我还注意到这些子列表是使用 List.of
创建的,其中 returns 和不可变列表,任何修改此类集合的尝试都会抛出 UnsupportedException。如果它们符合您的实际代码,您可能希望像这样编写它们:
var l1 = new ArrayList(List.of("abc", "def", "acd")); //Conversion constructor
var l2 = new ArrayList(List.of("bed", "fed", "aed")); //Conversion constructor
var c1 = new Custom(1, l1);
var c2 = new Custom(2, l2);
var l3 = new ArrayList(List.of(c1, c2)); //Conversion constructor
var l4 = new ArrayList(List.of(c2)); //Conversion constructor
var cc1 = new CustomContainer(3, l3);
var cc2 = new CustomContainer(4, l4);
var containers = new ArrayList<>(List.of(cc1, cc2)); //Conversion constructor
通过使用转换构造函数,您基本上是在批量操作中添加从不可变 list
到可变 ArrayList
的所有元素。
假设我们有一个 3 维对象列表。
class Custom {
int id;
List<String> list;
Custom(id, list) { // Constructor }
// Getters and Setters
}
class CustomContainer {
int id;
List<Custom> list;
CustomContainer(id, list) { // Constructor }
// Getters and Setters
}
var l1 = List.of("abc", "def", "acd");
var l2 = List.of("bed", "fed", "aed");
var c1 = new Custom(1, l1);
var c2 = new Custom(2, l2);
var l3 = List.of(c1, c2);
var l4 = List.of(c2);
var cc1 = new CustomContainer(3, l3)
var cc2 = new CustomContainer(4, l4)
var containers = List.of(cc1, cc2);
说我想过滤“容器”,这样我想从最里面的列表中删除以“a”开头的所有元素。 因此,输出应该是(考虑到 toString() 仅打印列表中的字符串):
[[["def"],["bed", "fed"]], [["bed", "fed"]]]
如何在 Java 中使用 Streams 获取此内容?
由于您需要处理最内层的集合,但又想收集最外层的元素,因此您需要处理 CustomContainer
的 List
,然后为每个元素的列表调用 foreach
(收集方法不是流方法)和removeIf
。
List<CustomContainer> res = containers.stream()
.peek(container -> container.getList().forEach(custom -> custom.getList().removeIf(str -> str.startsWith("a"))))
.collect(Collectors.toList());
在测试您的代码时,我还注意到这些子列表是使用 List.of
创建的,其中 returns 和不可变列表,任何修改此类集合的尝试都会抛出 UnsupportedException。如果它们符合您的实际代码,您可能希望像这样编写它们:
var l1 = new ArrayList(List.of("abc", "def", "acd")); //Conversion constructor
var l2 = new ArrayList(List.of("bed", "fed", "aed")); //Conversion constructor
var c1 = new Custom(1, l1);
var c2 = new Custom(2, l2);
var l3 = new ArrayList(List.of(c1, c2)); //Conversion constructor
var l4 = new ArrayList(List.of(c2)); //Conversion constructor
var cc1 = new CustomContainer(3, l3);
var cc2 = new CustomContainer(4, l4);
var containers = new ArrayList<>(List.of(cc1, cc2)); //Conversion constructor
通过使用转换构造函数,您基本上是在批量操作中添加从不可变 list
到可变 ArrayList
的所有元素。