2013-09-19 2 views
5

мне нужно использовать карту со списком внутри:Инициализация карты с помощью списка внутри

Map<String, List<String>> keyToGroup = new HashMap<String, ArrayList<String>>(); 

Я получаю ошибку компиляции на этой линии в затмении.

Единственная вещь работает, кажется, изменения внутри списка в карте для ArrayList

Map<String, ArrayList<String>> keyToGroup = new HashMap<String, ArrayList<String>>(); 

я должен был изменить сигнатуру методов много интерфейсов, но я до сих пор не понимаю; почему не первое определение работает?

Разве это не то же самое, не

Map<String, List<String>> keyToGroup 

&

Map<String, ArrayList<String>> 

быть такой же?

ответ

8

Нет, это не так. Рассмотрим это:

Map<String, List<String>> keyToGroup = new HashMap<String, ArrayList<String>>(); 
keyToGroup.put("foo", new LinkedList<String>()); 

Вторая линия это хорошо, потому что LinkedList<String> является List<String> - но это не логически нормально с точки зрения добавления его к HashMap<String, ArrayList<String>>, потому что LinkedList<String> является неArrayList<String>.

Чтобы было понятнее:

Map<String, ArrayList<String>> map1 = new HashMap<String, ArrayList<String>>(); 
Map<String, List<String>> map2 = map1; // This is invalid 
map2.put("foo", new LinkedList<String>()); 
ArrayList<String> oops = map1.get("foo"); // Because this would be broken 

Это не только случай с коллекциями как аргумент типа. Это даже проще, чтобы увидеть с нормальным наследованием:

List<Banana> bunchOfBananas = new ArrayList<Banana>(); 
List<Fruit> fruitBowl = bunchOfBananas; // Invalid! 
fruitBowl.add(new Apple()); 
Banana banana = bunchOfBananas.get(0); 

Хотя каждый банан является фрукты, поэтому «коллекция бананов» является «сбор фруктов * в смысле выборки их, не каждый фрукт не является банан.

вы можете использовать wildcard parameterized types, чтобы помочь в некоторых случаях, но это зависит от того, что вы пытаетесь достичь.

+0

+1, хороший, логичный & фирменный. Благодарю. – TheO

0

нет, они не являются. Дженерики не в Java ковариантны.

Если они ковариантны, вы можете логически поместить любой тип List вместо ArrayList, который побеждает цель создания дженериков.

Рассмотрите возможность чтения Эффективная Java (2-е издание) Глава 5: Дженерики, которые имеют очень хорошее объяснение Generics.

Другой хорошо читать это http://www.angelikalanger.com/GenericsFAQ/JavaGenericsFAQ.html

0

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

Map<String, ArrayList<String>> keyToGroup = new HashMap<String, ArrayList<String>>(); 

В случае любого списка просто использовать:

Map<String, List<String>> keyToGroup = new HashMap<String, List<String>>(); 
keyToGroup.put("arraylist", new ArrayList<String()); 
keyToGroup.put("linkedlist", new LinkedList<String()); 

Кстати, второй вариант, как правило, лучше с точки зрения дизайна, так что если вы пока не знаю точно - сначала попробуйте использовать второй вариант.

+0

Мне нравится этот подход, он гибкий; но моя проблема заключалась в том, что мне нужна эта переменная в качестве параметра метода, и мне нужно прочитать добавленные значения (out Parameter); поэтому я не думаю, что это сработает, потому что List еще не запущен. – TheO

Смежные вопросы