Java 8 Streams按可选属性分组
作者:互联网
我正在尝试通过属性分组计算值.计算值是可选的-更清楚一点,他是一个简化的示例:
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的“ someAttribute”进行过滤.
例如,我有这样的东西:
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语句中是否有更清洁或更正确的方法来执行此操作?
解决方法:
您可以使用过滤器删除条目,如下所示.
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);
}
或者,使用对对象,可以避免为每个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;
}
}
标签:collectors,java-stream,optional,java 来源: https://codeday.me/bug/20191118/2025152.html