2016-10-20 7 views
2

속성에서 계산 된 값을 그룹화하려고합니다. 그것은 나에 속하지 않기 때문에선택적 속성으로 Java 8 스트림 그룹화

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) 

내가 변환기의 방법을 변경할 수 없습니다 : - 계산 된 값은 선택 사항입니다 좀 더 명확하게하기 위해, 자신은 간단한 예이다.

나는 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 문에없는 경우 내지도에서 아무것도하지 않을 것이다. 나는 이런 식으로 뭔가를했다 :

나는 그 키에 의해 그룹화 된지도에서 아무것도를 제거 할 수 있다고 생각하지만, 깨끗한 또는 groupingBy 문에이 작업을 수행하는 더 정확한 방법이
fooBySomeNames.remove("") 

?

답변

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

또는 한 쌍의 객체와 함께, 당신은 모든 푸에 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; 
    } 
}