Сопоставить <String, Map <String, Car >> с List <Car>, используя Java 8 - PullRequest
3 голосов
/ 14 мая 2019

Допустим, у меня есть структура, описанная в заголовке:

Map<String, Map<String, Car>> mapNeighborhood

, которая содержит все автомобили в окрестности, проиндексированные по адресу и табличке соответственно.Я хочу выбрать все красные машины, чтобы перекрасить их в черный.Чтобы выполнить эту задачу, я попытался «выровнять» обе карты и получить список с использованием Java 8. Получив список, применяя предикат, я могу выбрать только красные автомобили и применить перерисовку.

List<Car> listCars = new ArrayList<Car>();

mapNeighborhood.values().forEach(map -> map.values()
                                           .forEach(car -> listCars.add(car)));

listCars.stream().filter(Car::isRed)
                 .forEach(car -> car.repaint(Color.Black));

Я уверен, что вы можете добиться того же, используя только одну строку в Java 8, но я думаю, что вы можете потерять разборчивость.

Мой вопрос: есть ли другой менее подробный способ сглаживания Карт всписок?Может быть, используя flatMap.Заранее спасибо.

Ответы [ 4 ]

9 голосов
/ 14 мая 2019

Вам не нужно промежуточное звено List

mapNeighborhood.values().stream()
                        .flatMap(byPlate -> byPlate.values().stream())
                        .filter(Car::isRed)
                        .forEach(car -> car.repaint(Color.Black))

Я думаю, что это и больше читабельно, чем ваш код, и короче. Это также объективно намного более эффективно, как во времени, так и в пространстве.


Также обратите внимание, что Car::isRed несколько странно, так как вам потребуется проверка для каждого возможного Color на Car - добавьте новый color для сезона, переопределение Car.

Color::isRed имеет гораздо больше смысла, с Car орудиями Colored или некоторыми другими

interface Colored {
    Color getColor();
}

// in Color
public static boolean isRed(Colored colored) {
    return Objects.equals(colored.getColor(), RED);
}
3 голосов
/ 14 мая 2019

Мой результат такой же, как у @Boris, но я покажу вам, как этого добиться с IntelliJ:

for (Map<String, Car> value : mapNeighborhood.values()) {
    for (Car car : value.values()) {
        if (car.isRed()) {
            car.repaint(Color.BLACK);
        }
    }
}

Затем вы перемещаете курсор в первое слово «for», нажимаете Alt-Enter, затем выбираете «Заменить на ForEach», тада, вот и мы:

mapNeighborhood.values().stream()
                        .flatMap(value -> value.values().stream())
                        .filter(Car::isRed)
                        .forEach(car -> car.repaint(Color.BLACK));

В любом цикле вы можете попытаться использовать IntelliJ, чтобы помочь вам интеллектуально конвертировать в стиль java 8

0 голосов
/ 14 мая 2019

Это может быть полезно.

mapNeighborhood.values().stream()
                        .map(Map::values)
                        .flatMap(Collection::stream)
                        .filter(car -> car.getColor().equalsIgnoreCase("red"))
                        .forEach(car -> car.repaint("black"));
0 голосов
/ 14 мая 2019

Вот способ, которым я пытался

List<Car> collect = mapNeighborhood.values().stream()
                                            .map(Map::values)
                                            .flatMap(Collection::stream)
                                            .collect(Collectors.toList());

Тогда вы можете продолжить и управлять списком автомобилей.

...