2016-04-24 4 views
1

У меня есть ситуации, когда у меня естьJava 8 flatmap, поток, собирать

class A { 
    private B b; 

    public B getB() { 
     return b; 
    } 
} 

и другой класс B

class B { 
    private List<C> c; 

    public List<C> getListC() { 
     return c; 
    } 
} 

Теперь класс C содержит две переменные экземпляра

class C { 
    private int id; 
    private String name; 

    public int getId() { 
     return id; 
    } 

    public String getName() { 
     return name; 
    } 
} 

сейчас Я хочу достичь ниже, используя java 8

List<C> newListC = a.getB().getListC(); 
Map<Integer, String> map = new HashMap<>(); 

for(C c : newListC) { 
    map.put(c.getId,c.getName()); 
} 

Я пробовал много раз, но каждый раз, когда сталкивался с различными проблемами. Мой код: сообщение

Optional<A> a=Optional.of(new A()); 
    Map<Integer, String> map= a.map(A::getB) 
          .flatMap(b -> 
            b.getListC() 
              .stream() 
              .collect(Collectors.toMap(
             C::getId, 
             C::getName 
                ) 
              ) 
          ); 

Ошибка:

Error:(164, 33) java: incompatible types: no instance(s) of type 
variable(s) U,R,A,capture#1 of ?,T,K,U exist so that 
java.util.Optional<U> conforms to 
java.util.Map<java.lang.Integer,java.lang.String> 

Заранее спасибо

+10

'a.getB(). GetListC(). Stream(). Collect (toMap (C :: getId, C :: getName))'. Вы передумали это. –

+1

Что означал @BoristheSpider, было 'Collectors.toMap', если только он не сделал статический импорт, но для этого лучше быть немного более явным. – Andreas

+1

@boris может оставить свой комментарий в качестве ответа – Bohemian

ответ

1

Вы не можете flatMap a Optional до Map; функция должна вернуть Optional. С другой стороны, так как функция не возвращает Optional, flatMap ненужно и обычный map будет делать:

Map<Integer, String> map = Optional.of(new A()) 
    .map(A::getB) 
    .map(b -> b.getListC().stream().collect(Collectors.toMap(C::getId, C::getName))) 
    .orElse(Collections.emptyMap()); 

Но так как результат new A() не может быть пустым (и используя of вместо ofNullable признает это), косвенная обработка в начале цепочки ненужна:

Map<Integer, String> map = Optional.ofNullable(new A().getB()) 
    .map(b -> b.getListC().stream().collect(Collectors.toMap(C::getId, C::getName))) 
    .orElse(Collections.emptyMap()); 

Но обратите внимание, что только допустимость пустых результата getB обрабатывается, как функция перешла к следующему шагу отображения безоговорочно вызывает stream() в списке, возвращаемом getListC. Но возвращение null, где ожидается List, плохой стиль кодирования; вы всегда можете вернуть пустой список, чтобы представить отсутствие значений.

Может быть, ваша путаница проистекает из Stream на основе альтернативного решения:

Map<Integer, String> map = Stream.of(new A().getB()) 
    .filter(Objects::nonNull) 
    .flatMap(b -> b.getListC().stream()) 
    .collect(Collectors.toMap(C::getId, C::getName)); 

Здесь поток, состоящий из более чем один элемент создается, а затем flatMap ИНГ его элементов списка, возвращаемого getListC ...

2

Хотя я ударил пару ошибок компиляции, как я могу видеть несколько опечаток, но

Try:

List<C> newListC= new A().getB().getListC(); 

    Map<Integer, String> stringMap = newListC.stream() 
      .collect(Collectors 
        .toMap(C::getId, C::getName)); 

При условии, что вы исправили свои проблемы с компиляцией, он должен излучать результат, эквивалентный не-потоковой версии карты.

+0

Я не могу использовать Список newListC = new A(). GetB(). GetListC(); Я хочу сохранить его в серии карт или flatMap, так как напрямую это может привести к исключению нулевого указателя –

+1

Как я уже упоминал, есть ошибки компиляции, поэтому невозможно дать точное решение. См. Раздел Как создать минимальный, полный и проверенный пример? http://stackoverflow.com/help/mcve – Saleem