Java 8 FlatMap - 以嵌套形式添加项目并使用 FlatMap 检索对象
Java 8 FlatMap - Add items in a nested form and retrieve object using FlatMap
我有一个对象 Foo
,其中包含 Bar
的列表。 类描述如下:
class Foo {
String name;
List<Bar> bars = new ArrayList<Bar>();
Foo(String name){
this.name = name;
}
}
class Bar {
String name;
Bar(String name){
this.name = name;
}
}
现在,我正在创建一个 Foo
个对象的列表,每个对象包含一个 Bar
个对象的列表,如下所示:
IntStream
.range(1, 4)
.forEach(i -> foos.add(new Foo("Foo" + i)));
foos.forEach(f ->
IntStream.range(1,4)
.forEach(i -> f.bars.add(new Bar("Bar"+i+" -> "+f.name))));
然后在 Stream
上使用 flatMap
,如下所示:
foos.stream()
.flatMap(f -> f.bars.stream())
.forEach(i -> System.out.println("Bar Name : "+i.name));
如何使用 Java Stream
和 lambda 在一次执行中完成所有这些事情?有没有其他方法可以用 Java 8 风格做这种事情?
您可以在 mapToObj
中生成 Foo
个实例而不是 forEach
:
IntStream.range(1, 4)
.mapToObj (i -> {Foo foo = new Foo("Foo" + i);
foo.bars =
IntStream.range(1,4)
.mapToObj(j -> new Bar("Bar"+j+" -> "+foo.name))
.collect(Collectors.toList());
return foo;
})
.flatMap (f -> f.bars.stream())
.forEach(i -> System.out.println("Bar Name : "+i.name));
但是,这不会将创建的 Foo
个实例存储在 List
中。如果要将它们存储在 List
中,要么将操作拆分为 2 个 Stream
管道(第一个以 collect(Collectors.toList())
结尾)或使用 peek(f->foos.add(f))
添加 Foo
实例到 foos
List
中(这将要求您在 运行 管道之前实例化 foos
List
)。
编辑:
修正了一些拼写错误并测试了代码:
Bar Name : Bar1 -> Foo1
Bar Name : Bar2 -> Foo1
Bar Name : Bar3 -> Foo1
Bar Name : Bar1 -> Foo2
Bar Name : Bar2 -> Foo2
Bar Name : Bar3 -> Foo2
Bar Name : Bar1 -> Foo3
Bar Name : Bar2 -> Foo3
Bar Name : Bar3 -> Foo3
我还通过使用 peek 和 mapToObject 的以下管道操作获得了解决方案...
IntStream.range(1, 4)
.mapToObj(i -> new Foo("Foo"+i))
.peek(f -> IntStream.range(1, 4)
.mapToObj(i -> new Bar("Bar"+i+"->"+f.name))
.forEach(f.bars::add))
.flatMap(f -> f.bars.stream())
.forEach(b -> System.out.println("Bar : "+b.name));
如果您要做的只是打印 Bar
实例的名称,那么 Foo
和 Bar
实例的整个构造和集合都已过时。您可以直接生成并打印名称:
IntStream.range(1, 4)
.mapToObj(i -> "Foo" + i)
.flatMap(name -> IntStream.range(1, 4)
.mapToObj(i -> "Bar" + i + "->" + name))
.forEach(System.out::println);
我有一个对象 Foo
,其中包含 Bar
的列表。 类描述如下:
class Foo {
String name;
List<Bar> bars = new ArrayList<Bar>();
Foo(String name){
this.name = name;
}
}
class Bar {
String name;
Bar(String name){
this.name = name;
}
}
现在,我正在创建一个 Foo
个对象的列表,每个对象包含一个 Bar
个对象的列表,如下所示:
IntStream
.range(1, 4)
.forEach(i -> foos.add(new Foo("Foo" + i)));
foos.forEach(f ->
IntStream.range(1,4)
.forEach(i -> f.bars.add(new Bar("Bar"+i+" -> "+f.name))));
然后在 Stream
上使用 flatMap
,如下所示:
foos.stream()
.flatMap(f -> f.bars.stream())
.forEach(i -> System.out.println("Bar Name : "+i.name));
如何使用 Java Stream
和 lambda 在一次执行中完成所有这些事情?有没有其他方法可以用 Java 8 风格做这种事情?
您可以在 mapToObj
中生成 Foo
个实例而不是 forEach
:
IntStream.range(1, 4)
.mapToObj (i -> {Foo foo = new Foo("Foo" + i);
foo.bars =
IntStream.range(1,4)
.mapToObj(j -> new Bar("Bar"+j+" -> "+foo.name))
.collect(Collectors.toList());
return foo;
})
.flatMap (f -> f.bars.stream())
.forEach(i -> System.out.println("Bar Name : "+i.name));
但是,这不会将创建的 Foo
个实例存储在 List
中。如果要将它们存储在 List
中,要么将操作拆分为 2 个 Stream
管道(第一个以 collect(Collectors.toList())
结尾)或使用 peek(f->foos.add(f))
添加 Foo
实例到 foos
List
中(这将要求您在 运行 管道之前实例化 foos
List
)。
编辑:
修正了一些拼写错误并测试了代码:
Bar Name : Bar1 -> Foo1
Bar Name : Bar2 -> Foo1
Bar Name : Bar3 -> Foo1
Bar Name : Bar1 -> Foo2
Bar Name : Bar2 -> Foo2
Bar Name : Bar3 -> Foo2
Bar Name : Bar1 -> Foo3
Bar Name : Bar2 -> Foo3
Bar Name : Bar3 -> Foo3
我还通过使用 peek 和 mapToObject 的以下管道操作获得了解决方案...
IntStream.range(1, 4)
.mapToObj(i -> new Foo("Foo"+i))
.peek(f -> IntStream.range(1, 4)
.mapToObj(i -> new Bar("Bar"+i+"->"+f.name))
.forEach(f.bars::add))
.flatMap(f -> f.bars.stream())
.forEach(b -> System.out.println("Bar : "+b.name));
如果您要做的只是打印 Bar
实例的名称,那么 Foo
和 Bar
实例的整个构造和集合都已过时。您可以直接生成并打印名称:
IntStream.range(1, 4)
.mapToObj(i -> "Foo" + i)
.flatMap(name -> IntStream.range(1, 4)
.mapToObj(i -> "Bar" + i + "->" + name))
.forEach(System.out::println);