Java Map <String, Set <String>> типы инициализации - PullRequest
0 голосов
/ 02 ноября 2018

У меня есть следующая карта: Map<String, Set<String>>, которую мне нужно инициализировать. Это само по себе не проблема. Тем не менее, поскольку я хочу, чтобы Set сохранял порядок вставки, я подумал об инициализации всей конструкции с помощью new LinkedHashMap<String, LinkedHashSet<String>>();, но это вынуждает меня изменить карту на: Map<String, LinkedHashSet<String>>.

Почему я не могу использовать интерфейс, если при инициализации указываю определенный тип? Или как лучше обеспечить реализацию вложенного типа?


Чтобы понять, почему я хочу это сделать, вот код:

private void sortMap(Map<String, Map<Date, Map<String, Long>>> dataMap) {
    Map<String, Set<String>> sortedNames = new LinkedHashMap<String, Set<String>>(); // <-- this initialization
    for (Map.Entry<String, Map<Date, Map<String, Long>>> entry : dataMap.entrySet()) {
        sortedNames.put(entry.getKey(), entry.getValue().get(getCurrentMonthDate()).keySet());
    }
}

EDIT

С помощью принятого ответа я придумал это решение, которое, кажется, прекрасно работает для меня:

Map<String, Set<String>> sortedNames = dataMap.entrySet().stream()
        .map(e -> new AbstractMap.SimpleEntry<String, LinkedHashSet<String>>(e.getKey(),
                e.getValue().get(getCurrentMonthDate()).keySet().stream()
                        .collect(Collectors.toCollection(LinkedHashSet<String>::new))))
        .collect(Collectors.toMap(Entry::getKey, Entry::getValue));

Ответы [ 2 ]

0 голосов
/ 02 ноября 2018

Универсальные типы не являются ковариантными, поэтому вы не можете присвоить LinkedHashMap<String, LinkedHashSet<String>> Map<String, Set<String>>.

Если вам нужно, чтобы значения карты были только LinkedHashSet, тогда вы должны объявить карту как Map<String, LinkedHashSet<String>>.

Однако в этом нет необходимости, поскольку вы можете вызвать map.put с подтипом Set<String>:

Map<String, Set<String>> map = new LinkedHashMap<>();       
map.put("key", new LinkedHashSet<String>());

Что по-прежнему позволяет вам программировать на интерфейс Set.


Вот более простая версия вашего кода с использованием потокового API.

Date curretMonthDate = getCurrentMonthDate();
Map<String, Set<String>> sortedNames = dataMap.entrySet().stream()
.map(e -> new AbstractMap.SimpleEntry<String, LinkedHashSet<String>>(e.getKey(),
                    e.getValue()
                    .entrySet()
                    .stream()
                    .filter(inner -> inner.getKey().equals(curretMonthDate))
                    .flatMap(subEntry -> subEntry
                                .getValue()
                                .entrySet()
                                .stream()
                                .map(Entry::getKey))
        .collect(Collectors.toCollection(LinkedHashSet<String>::new))))
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
0 голосов
/ 02 ноября 2018

Затем выполните инициализацию следующим образом.

Map<String, Set<String>> test = new LinkedHashMap<>();
// initialize to LinkedHashSet<> when putting elements
test.put("key", new LinkedHashSet<>());

Вы не можете использовать Map<String, Set<String>> test = new LinkedHashMap<String, LinkedHashSet<String>>(), потому что LinkedHashMap<String, LinkedHashSet<String>>(); не является подтипом Map<String, Set<String>>.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...