2016-10-14 2 views
3

У меня есть эти два примера кода:Java лучшая реализация 8 Многоуровневая flatMap

Код A:

Stream<String> aStream = firstLevelList.stream() 
          .flatMap(firstLevelElement -> firstLevelElement.getSecondLevelList().stream() 
           .flatMap(secondLevelElement -> secondLevelElement.getThirdLevelList().stream() 
            .map(thirdLevelElement -> thirdLevelElement.toString()))); 

Код B:

Оба имеют точно такой же результат, который лучшая реализация? Зачем?

+0

, если вы можете показать, что вы пытаетесь архивировать, скорее всего, может быть лучше подходит – emotionlessbananas

+1

Это не имеет значения. Выберите то, что вы считаете лучше. –

+1

Нет технической разницы, но, очевидно, вторая, избегая глубокого вложения, повышает читаемость, так как вам не нужно угадывать привязку привязки конца '))));' и вы не склонны поднимать отступы в каждой строке ... – Holger

ответ

1

Вариант 1

Следующая читает хорошо и чувствует себя более распространенным:

firstLevelList.stream() 
     .flatMap(firstLevelElement -> firstLevelElement.getSecondLevelList().stream()) 
     .flatMap(secondLevelElement -> secondLevelElement.getThirdLevelList().stream()) 
     .map(Object::toString); 

Это позволяет избежать вложенности, как @Holger отметил, что очень важно для читателя.

Вариант 2

В качестве альтернативы можно использовать различные отступы для гнездования, если это не расходится с остальной частью кода базового типа:

firstLevelList.stream().flatMap(
     firstLevelElement -> firstLevelElement.getSecondLevelList().stream().flatMap(
       secondLevelElement -> secondLevelElement.getThirdLevelList().stream().map(Object::toString) 
     ) 
); 

Вариант 3

Если все еще кажется слишком загадочным, мы можем извлечь переменные или методы для обозначения разных потоков:

firstLevelList.stream().flatMap(
     firstLevelElement -> firstLevelElement.getSecondLevelList().stream().flatMap(
       secondLevelElement -> getThirdLevelStream(secondLevelElement) 
     ) 
); 

Stream<String> getThirdLevelStream(SecondLevelElement secondLevelElement) { 
    return secondLevelElement.getThirdLevelList().stream().map(Object::toString); 
} 

Вариант 4

Мы можем переместить эти методы к классам элементов уважая теперь Law of Demeter:

firstLevelList.stream().flatMap(FirstLevelElement::getSecondLevelStream); 

class FirstLevelElement { 

    Stream<String> getSecondLevelStream() { 
     return this.getSecondLevelList().stream().flatMap(SecondLevelElement::getThirdLevelStream); 
    } 

    Collection<SecondLevelElement> getSecondLevelList() {...} 
} 

class SecondLevelElement { 

    Stream<String> getThirdLevelStream() { 
     return this.getThirdLevelList().stream().map(Object::toString); 
    } 

    Collection<ThirdLevelElement> getThirdLevelList() {...} 
} 

Это добавит некоторую ценность, если методы потока повторно используются где-то еще в код.

Заключение

Различные аргументы могут быть сделаны о какой из этих вариантов лучше. В общем, все они прекрасно.

0

Я предпочитаю ссылки метод для опрятности:

Stream<String> aStream = firstLevelList.stream() 
    .map(FirstLevelElement::getSecondLevelList) 
    .flatMap(List::stream) 
    .map(SecondLevelElement::getThirdLevelList) 
    .flatMap(List::stream) 
    .map(Object::toString); 
Смежные вопросы