Правильный способ инициализации HashMap и может ли HashMap содержать различные типы значений? - PullRequest
61 голосов
/ 28 августа 2009

Итак, у меня есть два вопроса о HashMap s на Java:

  1. Как правильно инициализировать HashMap? Я думаю, что в моей ситуации лучше всего использовать:

    HashMap x = new HashMap();
    

    Но Eclipse продолжает предлагать мне использовать:

    HashMap<something, something> map = new HashMap();
    

    Что лучше?

  2. Может ли HashMap содержать различные типы объектов / типов данных в качестве значений? Например, будет ли это работать и будет хорошо:

    map.put("one", 1);
    map.put("two", {1, 2});
    map.put("three", "hello");
    

    В первом put() я хочу int в качестве значения, во втором int[] и третьем строке. Это нормально делать в Java с HashMap s? Кроме того, можно ли хранить HashMap как значение в пределах HashMap?

Ответы [ 8 ]

100 голосов
/ 28 августа 2009

Это действительно зависит от того, какой тип безопасности вам нужен. Неуниверсальный способ сделать это лучше всего сделать так:

 Map x = new HashMap();

Обратите внимание, что x напечатано как Map. это значительно упрощает изменение реализаций (на TreeMap или LinkedHashMap) в будущем.

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

Map<String, Object> x = new HashMap<String, Object>();

В Java 7 и более поздних версиях вы можете сделать

Map<String, Object> x = new HashMap<>();

Выше, хотя и более многословно, избегает предупреждений компилятора. В этом случае содержимое HashMap может быть любым Object, так что это может быть Integer, int[] и т. Д., Что вы и делаете.

Если вы все еще используете Java 6, Библиотеки Гуавы (хотя это довольно легко сделать самостоятельно) имеет метод, называемый newHashMap(), который устраняет необходимость дублировать универсальный вводя информацию, когда вы делаете new. Он выводит тип из объявления переменной (это функция Java, недоступная в конструкторах до Java 7).

Кстати, когда вы добавляете int или другой примитив, Java автоматически его блокирует. Это означает, что код эквивалентен:

 x.put("one", Integer.valueOf(1));

Конечно, вы можете поместить HashMap в качестве значения в другое HashMap, но я думаю, что есть проблемы, если вы делаете это рекурсивно (то есть HashMap как само по себе значение).

14 голосов
/ 28 августа 2009

Это изменение сделано в Java 1.5. Первое, что вы перечислите, - это старый способ, а второй - новый.

Используя HashMap, вы можете делать такие вещи, как:

HashMap<String, Doohickey> ourMap = new HashMap<String, Doohickey>();

....

Doohickey result = ourMap.get("bob");

Если у вас нет типов на карте, вам придется сделать это:

Doohickey result = (Doohickey) ourMap.get("bob");

Это действительно очень полезно. Это поможет вам поймать ошибки и избежать написания всевозможных дополнительных бросков. Это была одна из моих любимых функций 1.5 (и новее).

Вы все еще можете поместить несколько объектов на карту, просто укажите это как Map, затем вы можете поместить любой объект (String, другую Map и Integer, а также три MyObjects, если вы склонны).

4 голосов
/ 28 августа 2009

Eclipse рекомендует объявлять тип HashMap, поскольку он обеспечивает некоторую безопасность типов. Конечно, звучит так, будто вы пытаетесь избежать безопасности типов из второй части.

Если вы хотите сделать последнее, попробуйте объявить карту как HashMap<String,Object>.

3 голосов
/ 28 августа 2009

То, как вы пишете, эквивалентно

HashMap<Object, Object> map = new HashMap<Object, Object>();

Что заключено в квадратные скобки, так это то, что вы сообщаете компилятору, что вы собираетесь поместить в HashMap, чтобы он мог выполнять проверку ошибок за вас. Если Object, Object - это то, что вы действительно хотите (вероятно, нет), вы должны явно объявить это. В общем, вы должны быть как можно более явными с объявлением, чтобы облегчить проверку ошибок компилятором. То, что вы описали, вероятно, должно быть объявлено так:

HashMap<String, Object> map = new HashMap<String, Object>();

Таким образом, вы, по крайней мере, объявляете, что ваши ключи будут строками, но ваши значения могут быть любыми. Просто не забудьте использовать приведение, когда вы получаете значение обратно.

2 голосов
/ 28 августа 2009

2-й использует дженерики, которые пришли с Java 1.5. Это уменьшит количество приведений в вашем коде и поможет вам отлавливать ошибки во время компиляции, а не во время выполнения. Тем не менее, это зависит от того, что вы кодируете. Быстрая и грязная карта для хранения нескольких объектов различных типов не нуждается в шаблонах. Но если на карте хранятся объекты, происходящие по типу, отличному от Object, это может стоить этого.

Предыдущий плакат неверен относительно массива на карте. Массив на самом деле является объектом, поэтому он является допустимым значением.

Map<String,Object> map = new HashMap<String,Object>();
map.put("one",1); // autoboxed to an object
map.put("two", new int[]{1,2} ); // array of ints is an object
map.put("three","hello"); // string is an object

Кроме того, поскольку HashMap является объектом, он также может быть значением в HashMap.

1 голос
/ 09 сентября 2016

Eclipse предлагает вам определить generic type, чтобы вы могли иметь type safety. Вы можете написать

Map m = new HashMap();

, который не обеспечивает безопасность типа, но следующее гарантирует безопасность типа

Map<Object,Object> = new HashMap<Object,Object>();

Object может быть любого типа, например String, Integer и т. Д.

1 голос
/ 28 августа 2009

HashMap может содержать любой объект в качестве значения, даже если это другой HashMap. Eclipse предлагает вам объявить типы, потому что это рекомендуемая практика для коллекций. под Java 5. Вы можете игнорировать предложения Eclipse.

В Java 5 int (или любой тип примитива) будет автоматически помещен в целое число (или другой соответствующий тип) при добавлении его в коллекцию. Будьте осторожны с этим, так как есть некоторые хитрости при использовании автобокса.

0 голосов
/ 28 августа 2009

В ответ на ваш второй вопрос: Да, HashMap может содержать различные типы объектов. Хорошая идея или нет, зависит от проблемы, которую вы пытаетесь решить.

Тем не менее, ваш пример не сработает. Значение int не является объектом. Вы должны использовать класс-оболочку Integer для хранения значения int в HashMap

...