Java 流合并和输出
Java stream merge and output
我有以下形式的对象列表:
public class Child
{
private Mom mom;
private Dad dad;
private String name;
private int age;
private boolean isAdopted;
}
我需要将这个列表转换为不同数据结构的列表,将具有相同妈妈和爸爸键的对象聚合在一起形成
public class Family
{
private Mom mom;
private Dad dad;
private Map<String, int> kids;
}
其中 'kids' 映射是所有儿童姓名到年龄的映射。
目前我正在做的翻译如下:
public Collection<Family> transform( final Collection<Child> children )
{
return children.stream()
.filter( child -> !child.getIsAdopted() )
.collect( ImmutableTable.toImmutableTable( child -> child.getMom(),
child -> child.getDad(),
child -> new HashMap<>(child.getName(), child.getAge() ),
(c1, c2) -> {
c1.getKids().putAll(c2.getKids());
return c1;
} ) )
.cellSet()
.stream()
.map( Table.Cell::getValue)
.collect( Collectors.toList() );
}
有没有办法让我在转换到最终列表之前不需要收集到中介table?
你可以这样做:
public static Collection<Family> transform( final Collection<Child> children ) {
Map<Mom, Map<Dad, Family>> families = new HashMap<>();
for (Child child : children) {
if (! child.isAdopted()) {
families.computeIfAbsent(child.getMom(), k -> new HashMap<>())
.computeIfAbsent(child.getDad(), k -> new Family(child.getMom(), child.getDad(), new HashMap<>()))
.getKids().put(child.getName(), child.getAge());
}
}
return families.values().stream().flatMap(m -> m.values().stream()).collect(Collectors.toList());
}
如果您可以使用 mom
和 dad
属性定义 GroupingKey
,则实现可以简化为:
@Getter
@AllArgsConstructor
class GroupingKey {
Mom mom;
Dad dad;
}
public List<Family> transformer( final Collection<Child> children ) {
return children.stream()
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(c -> new GroupingKey(c.getMom(), c.getDad())),
map -> map.entrySet().stream()
.map(e -> new Family(e.getKey().getMom(), e.getKey().getDad(),
e.getValue().stream().collect(Collectors.toMap(Child::getName, Child::getAge))))
.collect(Collectors.toList())));
}
或者如果不通过定义任何其他 class,您可以使用与 :
相同的方法转换对象
public List<Family> transform( final Collection<Child> children ) {
return children.stream()
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(c -> Arrays.asList(c.getMom(), c.getDad())),
map -> map.entrySet().stream()
.map(e -> new Family(((Mom) ((List) e.getKey()).get(0)), ((Dad) ((List) e.getKey()).get(1)),
e.getValue().stream().collect(Collectors.toMap(Child::getName, Child::getAge))))
.collect(Collectors.toList())));
}
我有以下形式的对象列表:
public class Child
{
private Mom mom;
private Dad dad;
private String name;
private int age;
private boolean isAdopted;
}
我需要将这个列表转换为不同数据结构的列表,将具有相同妈妈和爸爸键的对象聚合在一起形成
public class Family
{
private Mom mom;
private Dad dad;
private Map<String, int> kids;
}
其中 'kids' 映射是所有儿童姓名到年龄的映射。
目前我正在做的翻译如下:
public Collection<Family> transform( final Collection<Child> children )
{
return children.stream()
.filter( child -> !child.getIsAdopted() )
.collect( ImmutableTable.toImmutableTable( child -> child.getMom(),
child -> child.getDad(),
child -> new HashMap<>(child.getName(), child.getAge() ),
(c1, c2) -> {
c1.getKids().putAll(c2.getKids());
return c1;
} ) )
.cellSet()
.stream()
.map( Table.Cell::getValue)
.collect( Collectors.toList() );
}
有没有办法让我在转换到最终列表之前不需要收集到中介table?
你可以这样做:
public static Collection<Family> transform( final Collection<Child> children ) {
Map<Mom, Map<Dad, Family>> families = new HashMap<>();
for (Child child : children) {
if (! child.isAdopted()) {
families.computeIfAbsent(child.getMom(), k -> new HashMap<>())
.computeIfAbsent(child.getDad(), k -> new Family(child.getMom(), child.getDad(), new HashMap<>()))
.getKids().put(child.getName(), child.getAge());
}
}
return families.values().stream().flatMap(m -> m.values().stream()).collect(Collectors.toList());
}
如果您可以使用 mom
和 dad
属性定义 GroupingKey
,则实现可以简化为:
@Getter
@AllArgsConstructor
class GroupingKey {
Mom mom;
Dad dad;
}
public List<Family> transformer( final Collection<Child> children ) {
return children.stream()
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(c -> new GroupingKey(c.getMom(), c.getDad())),
map -> map.entrySet().stream()
.map(e -> new Family(e.getKey().getMom(), e.getKey().getDad(),
e.getValue().stream().collect(Collectors.toMap(Child::getName, Child::getAge))))
.collect(Collectors.toList())));
}
或者如果不通过定义任何其他 class,您可以使用与 :
相同的方法转换对象public List<Family> transform( final Collection<Child> children ) {
return children.stream()
.collect(Collectors.collectingAndThen(
Collectors.groupingBy(c -> Arrays.asList(c.getMom(), c.getDad())),
map -> map.entrySet().stream()
.map(e -> new Family(((Mom) ((List) e.getKey()).get(0)), ((Dad) ((List) e.getKey()).get(1)),
e.getValue().stream().collect(Collectors.toMap(Child::getName, Child::getAge))))
.collect(Collectors.toList())));
}