В какой-то момент в моем коде я создал Set<Map.Entry<K, V>>
с карты. Теперь я хочу воссоздать одну и ту же картографическую форму, поэтому я хочу преобразовать HashSet<Map.Entry<K, V>>
в HashMap<K, V>
. У Java есть собственный вызов для этого, или мне нужно перебирать установленные элементы и строить карту вручную?Convert Set <Map.Entry <K, V>> to HashMap <K, V>
ответ
В java нет встроенного API для прямого преобразования между HashSet
и HashMap
, вам необходимо выполнить итерацию по набору и используя Entry
заполнить карту.
один подход:
Map<Integer, String> map = new HashMap<Integer, String>();
//fill in map
Set<Entry<Integer, String>> set = map.entrySet();
Map<Integer, String> mapFromSet = new HashMap<Integer, String>();
for(Entry<Integer, String> entry : set)
{
mapFromSet.put(entry.getKey(), entry.getValue());
}
Хотя то, что цель здесь, если вы делаете какие-либо изменения в Set
, которые также будут отражены в Map
как набор возвращенного Map.entrySet
является резервное копирование с помощью Map
. См javadoc
ниже:
< Установить запись < Integer, String >> java.util.Map.entrySet()
Возвращает представление набора отображений содержится в этой карте. Набор , подкрепленный картой, поэтому изменения на карте отражаются в наборе, а - наоборот. Если карта изменена, когда итерация по набору выполняется (за исключением операции собственного удаления итератора или через операцию setValue в записи карты, возвращаемой итератором ), результаты итерации не определены. Набор поддерживает удаление элемента , которое удаляет соответствующее сопоставление с карты, с помощью операций Iterator.remove, Set.remove, removeAll, retainAll и clear . Он не поддерживает операции add или addAll.
Довольно короткое Java 8 решение. Может справляться с дублирующимися ключами.
Map<Integer, String> map = new HashMap<>();
//fill in map
Set<Map.Entry<Integer, String>> set = map.entrySet();
Map<Integer, String> mapFromSet = set.stream().collect(Collectors.toMap(Entry::getKey,
Entry::getValue,
(a,b)->b));
Edit: благодаря shmosel, который заслуживает большего кредита, чем я для этого
Нет. Ваш BiConsumer не объединяет Карты. – Joe
В приведенном выше коде метод accept BiConsumer никогда не вызывается. Я бы предпочел использовать null, но метод сбора глупо выбрасывает NPE в этом случае. – mikeyreilly
@mikeyreilly, [документация] (https://docs.oracle.com/javase/8/docs/api/java/util/stream/Stream.html#collect-java.util.function.Supplier-java.util .function.BiConsumer-java.util.function.BiConsumer-) явно не говорит, что объединитель никогда не вызывается для последовательного потока. Таким образом, вы просто нарушаете договор метода. –
В Java 8 с правильным объединителя
Map<Integer, String> map = new HashMap<>();
//fill in map
Set<Map.Entry<Integer, String>> set = map.entrySet();
Map<Integer, String> mapFromSet =set.stream().collect(HashMap::new,(t, u) -> t.put(u.getKey(), u.getValue()),
(Map mapToReturn, Map otherMap) ->
{
otherMap.entrySet().forEach((Map.Entry entry) -> {
mapToReturn.put(entry.getKey(),entry.getValue());
});
return mapToReturn;}););
Simpler Java-8 решение с Collectors.toMap
:
Map<Integer, String> mapFromSet = set.stream()
.collect(Collectors.toMap(Entry::getKey, Entry::getValue));
IllegalStateException
будет выброшен, если d встречается ключевой элемент.
Какие aboug NPE, если какое-либо значение равно нулю? –
По гуавы 19 вы можете использовать ImmutableMap.copyOf(Iterable<Map.Entry<K,V>>)
На Java 9, мы имеем Map.ofEntries. Они берут записи только как массив, поэтому вам нужно сначала преобразовать их с toArray()
и выбросить информацию о типе.
@SuppressWarnings("unchecked")
(Map.Entry<K, V>[] array = entrySet.toArray((Map.Entry<K, V>[])new Map.Entry<?, ?>[entrySet.size()]);
Map<K, V> map = Map.ofEntries(array);
Apache Commons имеет аналогичные методы.Commons Ланг ArrayUtils.toMap:
Map<Object, Object> map = ArrayUtils.toMap(entrySet.toArray());
// to recover the type...
@SuppressWarnings("unchecked")
Map<K, V> typedMap = (Map<K, V>)(Map<?, ?>)map;
Commons Коллекции MapUtils.putAll:
Map<K, V> map = MapUtils.putAll(new HashMap<K, V>(), entrySet.toArray());
Как вы создали '' Set' из Map', используя ключ или значение или пользовательской логики? кроме того, для 'HashSet''' HashMap' не существует 'native' метода. Вам нужно повторить и использовать некоторую логику, как при вводе в «HashMap», как вы выбираете ключ и значение. – harsh
@Paul теперь вопрос дает ясный смысл – harsh
Я не думаю, что «Map.Entry» предназначен для использования таким образом. Использует ли реализация, используемая 'HashMap' переопределить' hashCode' и 'equals', например? –