首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >将两个列表组合成一个map (Java)的最佳方式是什么?

将两个列表组合成一个map (Java)的最佳方式是什么?
EN

Stack Overflow用户
提问于 2009-12-03 20:46:02
回答 13查看 97.8K关注 0票数 78

使用for (String item: list)会很好,但是它只会遍历一个列表,并且您需要一个显式的迭代器来处理另一个列表。或者,您可以对这两者使用显式迭代器。

下面是这个问题的一个例子,以及一个使用索引for循环的解决方案:

代码语言:javascript
复制
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);
  }
}

输出:

代码语言:javascript
复制
{apple=123, orange=456, pear=789}

有没有更清晰的方法?也许在某个地方的集合API中?

EN

回答 13

Stack Overflow用户

回答已采纳

发布于 2009-12-03 20:52:34

由于键-值关系通过列表索引是隐式的,我认为显式使用列表索引的for循环解决方案实际上非常清楚-也很简短。

票数 20
EN

Stack Overflow用户

发布于 2016-07-22 06:03:41

这个问题提出已经有一段时间了,但这些天我偏爱这样的问题:

代码语言:javascript
复制
public static <K, V> Map<K, V> zipToMap(List<K> keys, List<V> values) {
    return IntStream.range(0, keys.size()).boxed()
            .collect(Collectors.toMap(keys::get, values::get));
}

对于那些不熟悉流的人来说,它所做的是获取一个从0到长度的IntStream,然后对它进行装箱,使它成为一个Stream<Integer>,这样它就可以被转换为一个对象,然后使用Collectors.toMap收集它们,其中一个供应商生成关键字,另一个供应商生成值。

这可以经得起一些验证(比如要求keys.size()小于values.size()),但作为一个简单的解决方案,它工作得很好。

编辑:上面的方法适用于任何具有固定时间查找的东西,但是如果你想要在相同的顺序上工作(仍然使用相同的模式),你可以这样做:

代码语言:javascript
复制
public static <K, V> Map<K, V> zipToMap(List<K> keys, List<V> values) {
    Iterator<K> keyIter = keys.iterator();
    Iterator<V> valIter = values.iterator();
    return IntStream.range(0, keys.size()).boxed()
            .collect(Collectors.toMap(_i -> keyIter.next(), _i -> valIter.next()));
}

输出是相同的(同样,缺少长度检查,等等)但是时间复杂度并不依赖于使用任何列表的get方法的实现。

票数 77
EN

Stack Overflow用户

发布于 2009-12-03 21:09:09

我经常使用下面的成语。我承认它是否更清晰是有争议的。

代码语言:javascript
复制
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 algorithm,它实际上需要对长度为n的列表进行n*n次操作。

正如13ren所指出的,当长度不匹配时,如果您试图在一个列表的末尾进行读取,则Iterator.next会抛出NoSuchElementException。所以你会得到更简洁但可能有点令人困惑的变体:

代码语言:javascript
复制
Iterator<String> i1 = names.iterator();
Iterator<String> i2 = things.iterator();
while (i1.hasNext() || i2.hasNext()) map.put(i1.next(), i2.next());
票数 49
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1839668

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档