簡體   English   中英

Java 8 Streams按可選屬性分組

[英]Java 8 Streams Grouping by an Optional Attribute

我試圖通過屬性的計算值進行分組。 計算出的值是可選的 - 為了更清楚一點,他是一個簡化的例子:

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);
}

或者,使用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;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM