Что лучший способ состоит в том, чтобы объединить два списка в карту (Java)?

Было бы хорошо использовать for (String item: list), но это только выполнит итерации через один список, и Вам был бы нужен явный итератор для другого списка. Или, Вы могли использовать явный итератор для обоих.

Вот пример проблемы и решение с помощью индексируемого for цикл вместо этого:

import java.util.*;
public class ListsToMap {
  static public void main(String[] args) {
    List<String> names = Arrays.asList("apple,orange,pear".split(","));
    List<String> things = Arrays.asList("123,456,789".split(","));
    Map<String,String> map = new LinkedHashMap<String,String>();  // ordered

    for (int i=0; i<names.size(); i++) {
      map.put(names.get(i), things.get(i));    // is there a clearer way?
    }

    System.out.println(map);
  }
}

Вывод:

{apple=123, orange=456, pear=789}

Существует ли более ясный путь? Возможно, в наборах API где-нибудь?

56
задан Soni Vashisht 1 August 2019 в 21:42
поделиться

6 ответов

Поскольку связь "ключ-значение" неявна через индекс списка, я думаю, что решение для цикла, которое явно использует индекс списка, на самом деле довольно ясное - и короткое хорошо.

19
ответ дан 26 November 2019 в 17:09
поделиться

Используйте Clojure. всего одна строка;)

 (zipmap list1 list2)
1
ответ дан 26 November 2019 в 17:09
поделиться

Вам даже не нужно ограничиваться струнами. Немного изменив код CPerkins:

Map<K, V> <K, V> combineListsIntoOrderedMap (List<K> keys, List<V> values) {
      if (keys.size() != values.size())
          throw new IllegalArgumentException ("Cannot combine lists with dissimilar sizes");
Map<K, V> map = new LinkedHashMap<K, V>();
for (int i=0; i<keys.size(); i++) {
  map.put(keys.get(i), values.get(i));
}
return map;

}

2
ответ дан 26 November 2019 в 17:09
поделиться

ArrayUtils # toMap () не объединяет два списка в карту, но делает это для двухмерного массива (так что это не совсем то, что вы ищете, но может быть интересно для использования в будущем ...)

5
ответ дан 26 November 2019 в 17:09
поделиться

Ваше решение, приведенное выше, конечно, верно, но ваш вопрос касался ясности, я отвечу на него.

Самый простой способ объединения двух списков - чтобы поместить комбинацию в метод с красивым понятным именем. Я только что взял ваше решение и извлек его в метод здесь:

Map<String,String> combineListsIntoOrderedMap (List<String> keys, List<String> values) {
    if (keys.size() != values.size())
        throw new IllegalArgumentException ("Cannot combine lists with dissimilar sizes");
    Map<String,String> map = new LinkedHashMap<String,String>();
    for (int i=0; i<keys.size(); i++) {
        map.put(keys.get(i), values.get(i));
    }
    return map;
}

И, конечно же, ваша отрефакторная main теперь будет выглядеть так:

static public void main(String[] args) {
    List<String> names = Arrays.asList("apple,orange,pear".split(","));
    List<String> things = Arrays.asList("123,456,789".split(","));
    Map<String,String> map = combineListsIntoOrderedMap (names, things);
    System.out.println(map);
}

Я не смог устоять перед проверкой длины.

9
ответ дан 26 November 2019 в 17:09
поделиться

Я часто использую следующую идиому. Я признаю, что вопрос о том, яснее ли это

Iterator<String> i1 = names.iterator();
Iterator<String> i2 = things.iterator();
while (i1.hasNext() && i2.hasNext()) {
    map.put(i1.next(), i2.next());
}
if (i1.hasNext() || i2.hasNext()) complainAboutSizes();

, имеет то преимущество, что он также работает для Коллекций и подобных вещей без произвольного доступа или без эффективного произвольного доступа, например LinkedList, TreeSets или SQL ResultSets. Например, если вы использовали исходный алгоритм для LinkedLists, у вас есть медленный алгоритм Shlemiel the painter , который на самом деле требует n * n операций для списков длины n.

As 13ren , вы также можете использовать тот факт, что Iterator. next выдает исключение NoSuchElementException, если вы пытаетесь прочитать после конца одного списка, когда длины не совпадают. Таким образом, вы получите более краткий, но, возможно, немного сбивающий с толку вариант:

Iterator<String> i1 = names.iterator();
Iterator<String> i2 = things.iterator();
while (i1.hasNext() || i2.hasNext()) map.put(i1.next(), i2.next());
41
ответ дан 26 November 2019 в 17:09
поделиться
Другие вопросы по тегам:

Похожие вопросы: