2013-06-06 3 views
1

Интересно, почему нет возможности построить карту со значениями в одном выражении. Или это? Я бы ожидалJava: построение карты из одного выражения?

new HashMap().add(key, value).add(key, value)...; 

Я не могу найти ничего подобного даже в коллекциях Commons.

Я пропустил какой-то способ в JDK или Commons?

+0

Гуава имеет что, см мой answer – fge

+0

Если вы хотите только JDK-решение, вы можете написать простой класс для этого, но он будет очень ограниченным. – Djon

+0

@ Djon действительно довольно легко реализовать строителя, см. Мой ответ – fge

ответ

2

Гуава имеет, что с его ImmutableMap:

final Map<Foo, Bar> map = ImmutableMap.of(foo1, bar1, foo2, bar2, etc, etc); 

Bonus: Имя ImmutableMap «s не ложь;)

Заметьте, что существует 5 версий метода .of(), поэтому до 5 пар ключ/значение. Более общий способ состоит в использовании строитель:

final Map<Foo, Bar> map = ImmutableMap.<Foo, Bar>builder() 
    .put(foo1, bar1) 
    .put(foo2, bar2) 
    .put(foo3, bar3) 
    .put(etc, etc) 
    .build(); 

Заметим, однако: эта карта не принимает нулевые ключи или значения.

В качестве альтернативы, это версия бедного человека ImmutableMap. Он использует классический шаблон построения. Обратите внимание, что не проверяет нулям:

public final class MapBuilder<K, V> 
{ 
    private final Map<K, V> map = new HashMap<K, V>(); 

    public MapBuilder<K, V> put(final K key, final V value) 
    { 
     map.put(key, value); 
     return this; 
    } 

    public Map<K, V> build() 
    { 
     // Return a mutable copy, so that the builder can be reused 
     return new HashMap<K, V>(map); 
    } 

    public Map<K, V> immutable() 
    { 
     // Return a copy wrapped into Collections.unmodifiableMap() 
     return Collections.unmodifiableMap(build()); 
    } 
} 

Затем вы можете использовать:

final Map<K, V> map = new MapBuilder<K, V>().put(...).put(...).immutable(); 
+0

Почему все в вашем коде окончательно? – Djon

+1

По чистой привычке.Я делаю переменные окончательными, где они могут быть, классы final, когда они не предназначены для наследования. – fge

+0

Я помещаю 'const' всякий раз, когда могу на C++, но я никогда не думал об этом в Java, странном мире. – Djon

2

Попробуйте это ..

Map<String, Integer> map = new HashMap<String, Integer>() 
{{ 
    put("One", 1); 
    put("Two", 2); 
    put("Three", 3); 
}}; 
+0

Хорошо, это допустимое решение, но создание подкласса для каждой необходимой мне карты ... –

+0

В приведенном выше коде используется 'block initialization'. Чтобы было ясно, он создает анонимный класс, единственным содержимым которого является блок, который будет называть несколько «put» –

1

Там нет ничего в Общин коллекции или в JDK. Но вы могли бы в качестве альтернативы использовать Guava и следующий код:

Map<String, String> mapInstance = ImmutableMap.<String, String> builder().put("key1", "value1").put("key2", "value2").build(); 
0
  • Если ваши ключи и Vales одного и того же типа, то имея такой метод:

    <K> Map<K, K> init(Map<K, K> map, K... args) { 
        K k = null; 
        for(K arg : args) { 
         if(k != null) { 
          map.put(k, arg); 
          k = null; 
         } else { 
          k = arg; 
         } 
        } 
        return map; 
    } 
    

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

    init(new HashMap<String, String>(), "k1", "v1", "k2", "v2"); 
    
  • Если ваши ключи и Vales имеют другого типа, то имея такой метод:

    <K, V> Map<K, V> init(Map<K, V> map, List<K> keys, List<V> values) { 
        for(int i = 0; i < keys.size(); i++) { 
         map.put(keys.get(i), values.get(i)); 
        } 
        return map; 
    } 
    

    Вы можете инициализировать карту с:

    init(new HashMap<String, Integer>(), 
        Arrays.asList("k1", "k2"), 
        Arrays.asList(1, 2)); 
    
+0

Err, 'Arrays.asList (" k1 "," k2 ")' работает одинаково хорошо – fge

+0

@fge , спасибо :) –

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