编程语言
首页 > 编程语言> > Java 8 Streams按可选属性分组

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