我正在尝试使用属性中的计算值进行分组。计算出的值是可选的 - 为了更加清楚,他是一个简化的例子:
class Foo:
int id;
Group group;
.. some other stuff
class Group:
String groupId;
... (some other stuff)
class SomeName:
String someAttribute;
class Converter:
public Optional<SomeName> getSomenameFromGroup(Group)
我无法更改Converter中的方法,因为它不属于我。
我有一个Foo列表,我希望按SomeName&#34; someAttribute&#34;过滤。
例如,我有这样的事情:
Map<String, List<Foo>> fooBySomeName =
fooList.stream().collect(Collectors
.groupingBy(foo -> {
Optional<SomeName> name =
converter.getSomenameFromGroup(foo.getGroup.getGroupId());
return name.isPresent() ? name.get().someAttribute() : "";
}));
但问题是,如果名称不在groupingBy语句中,我在地图中不需要任何内容。我有这样的事情:
fooBySomeNames.remove("")
我认为可以从地图中删除任何按该键分组的内容,但在groupingBy语句中是否有更清晰或更正确的方法?
答案 0 :(得分:3)
您可以使用过滤器删除条目,如下所示。
Map<String, List<Foo>> fooBySomeName = fooList.stream()
.filter(foo -> fooToSomeAttribute(foo).isPresent())
.collect(Collectors.groupingBy(foo -> fooToSomeAttribute(foo).get()));
private static Optional<String> fooToSomeAttribute(Foo foo)
{
return Optional.ofNullable(foo)
.map(Foo::getGroup)
.flatMap(new Converter()::getSomenameFromGroup)
.map(SomeName::getSomeAttribute);
}
或者,使用pair对象,可以避免每个Foo的someAttribute的双重计算:
Map<String, List<Foo>> fooBySomeName = fooList.stream()
.filter(Objects::nonNull)
.map(FooAndSomeAttribute::new)
.filter(pair -> pair.getSomeAttribute().isPresent())
.collect(Collectors.groupingBy(
pair -> pair.getSomeAttribute().get(),
Collectors.mapping(
FooAndSomeAttribute::getFoo,
Collectors.toList())));
private static class FooAndSomeAttribute
{
private final Foo foo;
private final Optional<String> someAttribute;
public FooAndSomeAttribute(Foo foo)
{
this.foo = foo;
this.someAttribute = Optional.ofNullable(foo)
.map(Foo::getGroup)
.flatMap(new Converter()::getSomenameFromGroup)
.map(SomeName::getSomeAttribute);
}
public Foo getFoo()
{
return foo;
}
public Optional<String> getSomeAttribute()
{
return someAttribute;
}
}