Java 8 Копирует карту с фильтром другой карты

#java-8 #hashmap #java-stream

#java-8 #хэш-карта #java-stream

Вопрос:

Я пытаюсь отфильтровать исходную карту путем сравнения с картой условий, которая имеет только наборы ключей с идентификатором. Основываясь на карте условий, я хочу выполнить фильтрацию по исходной карте.

Исходная карта, которая у меня есть, является,

 Map<Integer, AppFeatureDTO> appFeatureMap = new TreeMap<>();
  

что приведет к подобному,

 {
    "101": {
        "id": 101,
        "subFeature": {
            "1": {
                "id": 1,
                "title": "Title Value",
                "desc": "Description Value"
            }
        }
    },
    "102": {
        "id": 102,
        "subFeature": {
            "1": {
                "id": 1,
                "title": "Title Value",
                "desc": "Description Value"
            }
        }
    },
    "103": {
        "id": 103,
        "subFeature": {
            "1": {
                "id": 1,
                "title": "Title Value",
                "desc": "Description Value"
            },
            "2": {
                "id": 2,
                "title": "Title Value",
                "desc": "Description Value"
            },
            "3": {
                "id": 3,
                "title": "Title Value",
                "desc": "Description Value"
            },
            "4": {
                "id": 4,
                "title": "Title Value",
                "desc": "Description Value"
            }
        }
    }
}
  

и соответствующие классы являются:

 class AppFeatureDTO {
    private int id;
    private Map<Integer, AppSubFeatureDTO> subFeature;
}
class AppSubFeatureDTO{
    private int id;
    private String title;
    private String description;
}
  

тогда у меня есть карта фильтра,

 Map<Integer, FeatureDTO> conditionFilterMap = new TreeMap<>();
  

что приводит к подобному,

 {
    "101": {
        "id": 101,
        "subFeature": {
            "1": {
                "id": 1,
            }
        }
    },
    "103": {
        "id": 103,
        "subFeature": {
            "2": {
                "id": 2
            },
            "4": {
                "id": 4
            }
        }
    }
}
  

соответствующие классы для карты фильтров являются,

 class FeatureDTO {
    private int id;
    private Map<Integer, SubFeatureDTO> subFeature;
}
class SubFeatureDTO{
    private int id;
}
  

Я хочу отфильтровать результирующую карту, используя conditionFilterMap, например,

 {
"101": {
    "id": 101,
    "subFeature": {
        "1": {
            "id": 1,
            "title": "Title Value",
            "desc": "Description Value"
        }
    }
},
"103": {
    "id": 103,
    "subFeature": {
        "2": {
            "id": 2,
            "title": "Title Value",
            "desc": "Description Value"
        },
        "4": {
            "id": 4,
            "title": "Title Value",
            "desc": "Description Value"
        }
    }
}
  

}

Я использую spring ModelMapper для копирования AppFeatureDTO в FeatureDTO . Но, фильтруя карту, я не получил подсказки.

Не могли бы вы, пожалуйста, подсказать, как получить resultMap с помощью Java 8?

Даже я не мог представить простое решение, также использующее Java 7 или 6.

Ответ №1:

Предполагая, что ключ карты совпадает с полем id:

 Map<Integer, AppFeatureDTO> resultMap = conditionFilterMap.values().stream()
        .map(FeatureDTO::getId)
        .map(appFeatureMap::get)
        .collect(Collectors.toMap(AppFeatureDTO::getId, a -> new AppFeatureDTO(a.getId(),
                conditionFilterMap.get(a.getId()).getSubFeature().values().stream()
                        .map(SubFeatureDTO::getId)
                        .map(a.getSubFeature()::get)
                        .collect(Collectors.toMap(AppSubFeatureDTO::getId, x -> x)))));
  

Если вам нужно TreeMap , добавьте аргументы (a, b) -> a, TreeMap::new в Collectors.toMap вызовы.

Беспоточная версия на самом деле выглядит ничуть не хуже:

 Map<Integer, AppFeatureDTO> resultMap = new TreeMap<>();
for (FeatureDTO f : conditionFilterMap.values()) {
    AppFeatureDTO a = appFeatureMap.get(f.getId());
    Map<Integer, AppSubFeatureDTO> resultSub = new TreeMap<>();
    for (SubFeatureDTO s : f.getSubFeature().values()) {
        resultSub.put(s.getId(), a.getSubFeature().get(s.getId()));
    }
    resultMap.put(a.getId(), new AppFeatureDTO(a.getId(), resultSub));
}
  

Комментарии:

1. В этом также есть ошибка, можете ли вы просмотреть ее один раз. согласно 4-й строке первого фрагмента, вы передаете конструктору значение, подобное ключу. Это опечатка? или мне нужно создать конструктор?

2. @Shakthi вы можете переписать код для работы без такого конструктора, но это стало бы намного сложнее, поэтому рекомендуется создать такой конструктор.

3. @Shakthi Если у вас нет конструктора, создаете ли вы экземпляры с помощью new AppFeatureDTO() и вызываете setWhatever для установки значений полей? Если это так, я бы настоятельно рекомендовал добавить в ваши классы базовые конструкторы, которые принимают значения полей в качестве параметров, большинство IDE могут сгенерировать их для вас.