Java:如何将List转换为Map

Rac*_*hel 201 java list hashmap data-conversion data-structures

最近,我与一位同事讨论了如何在Java中转换List为最佳方式,Map以及是否有任何特定的好处.

我想知道最佳转换方法,如果有人能指导我,我会非常感激.

这是一个好方法:

List<Object[]> results;
Map<Integer, String> resultsMap = new HashMap<Integer, String>();
for (Object[] o : results) {
    resultsMap.put((Integer) o[0], (String) o[1]);
}
Run Code Online (Sandbox Code Playgroud)

Ale*_* C. 279

使用,您将能够使用Collectors类在一行中完成此操作.

Map<String, Item> map = 
    list.stream().collect(Collectors.toMap(Item::getKey, item -> item));
Run Code Online (Sandbox Code Playgroud)

简短演示:

import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class Test{
    public static void main (String [] args){
        List<Item> list = IntStream.rangeClosed(1, 4)
                                   .mapToObj(Item::new)
                                   .collect(Collectors.toList()); //[Item [i=1], Item [i=2], Item [i=3], Item [i=4]]

        Map<String, Item> map = 
            list.stream().collect(Collectors.toMap(Item::getKey, item -> item));

        map.forEach((k, v) -> System.out.println(k + " => " + v));
    }
}
class Item {

    private final int i;

    public Item(int i){
        this.i = i;
    }

    public String getKey(){
        return "Key-"+i;
    }

    @Override
    public String toString() {
        return "Item [i=" + i + "]";
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

Key-1 => Item [i=1]
Key-2 => Item [i=2]
Key-3 => Item [i=3]
Key-4 => Item [i=4]
Run Code Online (Sandbox Code Playgroud)

如评论中所述,您可以使用Function.identity()而不是item -> item,尽管我发现i -> i相当明确.

要完整注意,如果你的函数不是双射的,你可以使用二元运算符.例如,让我们考虑这个List以及对于int值的映射函数,计算模3的结果:

List<Integer> intList = Arrays.asList(1, 2, 3, 4, 5, 6);
Map<String, Integer> map = 
    intList.stream().collect(toMap(i -> String.valueOf(i % 3), i -> i));
Run Code Online (Sandbox Code Playgroud)

运行此代码时,您将收到错误消息java.lang.IllegalStateException: Duplicate key 1.这是因为1%3与4%3相同,因此在给定键映射功能的情况下具有相同的键值.在这种情况下,您可以提供合并运算符.

这是一个总和值的人; (i1, i2) -> i1 + i2;可以用方法参考替换Integer::sum.

Map<String, Integer> map = 
    intList.stream().collect(toMap(i -> String.valueOf(i % 3), 
                                   i -> i, 
                                   Integer::sum));
Run Code Online (Sandbox Code Playgroud)

现在输出:

0 => 9 (i.e 3 + 6)
1 => 5 (i.e 1 + 4)
2 => 7 (i.e 2 + 5)
Run Code Online (Sandbox Code Playgroud)

希望能帮助到你!:)

  • 更好地使用`Function.identity()`而不是`item - > item` (18认同)
  • @EmmanuelTouzery 嗯, `Function.identity()` 返回 `t -&gt; t;`。 (2认同)
  • 当然,两者都有效。我想这是一个品味问题。我发现 Function.identity() 更容易识别。 (2认同)

Jim*_*son 179

List<Item> list;
Map<Key,Item> map = new HashMap<Key,Item>();
for (Item i : list) map.put(i.getKey(),i);
Run Code Online (Sandbox Code Playgroud)

当然假设每个Item都有一个getKey()返回正确类型键的方法.

  • @Rachel——值是列表中的项目,键是使该项目唯一的东西,这由您决定。Jim 对“getKey()”的使用是任意的。 (2认同)

rip*_*234 114

如果此问题未以重复方式结束,则正确的答案是使用Google Collections:

Map<String,Role> mappedRoles = Maps.uniqueIndex(yourList, new Function<Role,String>() {
  public String apply(Role from) {
    return from.getName(); // or something else
  }});
Run Code Online (Sandbox Code Playgroud)

  • 这应该在顶部 (16认同)
  • "*[Guava](https://code.google.com/p/guava-libraries/#Important_Warnings)包含严格兼容的旧版,已弃用的Google收藏库**的超集.您不应再使用该库了.*"可能需要更新. (6认同)
  • 使用外部库进行如此简单的操作是过度的.那是一个非常弱的标准库的标志.在这种情况下,@ jim-garrison的答案是完全合理的.令人遗憾的是,java没有像"map"和"reduce"这样的有用方法,但并非完全必要. (3认同)
  • 这使用番石榴.不幸的是,Guava在Android上非常慢,因此不应该在Android项目中使用此解决方案. (2认同)

glt*_*lts 14

从Java 8开始,@ ZouZou使用Collectors.toMap收集器的答案肯定是解决这个问题的惯用方法.

由于这是一项非常常见的任务,我们可以将其变为静态实用程序.

这样,解决方案真正成为一个单线程.

/**
 * Returns a map where each entry is an item of {@code list} mapped by the
 * key produced by applying {@code mapper} to the item.
 *
 * @param list the list to map
 * @param mapper the function to produce the key from a list item
 * @return the resulting map
 * @throws IllegalStateException on duplicate key
 */
public static <K, T> Map<K, T> toMapBy(List<T> list,
        Function<? super T, ? extends K> mapper) {
    return list.stream().collect(Collectors.toMap(mapper, Function.identity()));
}
Run Code Online (Sandbox Code Playgroud)

以下是您将如何使用它List<Student>:

Map<Long, Student> studentsById = toMapBy(students, Student::getId);
Run Code Online (Sandbox Code Playgroud)


sta*_*Fan 12

使用Java 8,您可以执行以下操作:

Map<Key, Value> result= results
                       .stream()
                       .collect(Collectors.toMap(Value::getName,Function.identity()));
Run Code Online (Sandbox Code Playgroud)

Value 可以是您使用的任何对象.


Ste*_*Kuo 9

A ListMap概念上是不同的.A List是有序的项目集合.这些项可以包含重复项,并且项可能没有任何唯一标识符(键)的概念.A Map具有映射到键的值.每个键只能指向一个值.

因此,根据您List的项目,可能会或可能不会将其转换为Map.你List的物品没有重复吗?每个项目都有唯一的密钥吗?如果是这样,那么可以将它们放入Map.


And*_*ejs 8

使用Google 库中的Maps.uniqueIndex(...)也有一种简单的方法


i_a*_*ero 6

Alexis已经使用method 在Java 8中发布了答案toMap(keyMapper, valueMapper)。根据此方法实现的文档

不能保证返回的Map的类型,可变性,可序列化性或线程安全性。

因此,如果我们对Map接口的特定实现感兴趣,HashMap那么可以将重载形式用作:

Map<String, Item> map2 =
                itemList.stream().collect(Collectors.toMap(Item::getKey, //key for map
                        Function.identity(),    // value for map
                        (o,n) -> o,             // merge function in case of conflict with keys
                        HashMap::new));         // map factory - we want HashMap and not any Map implementation
Run Code Online (Sandbox Code Playgroud)

虽然无论是使用Function.identity()还是i->i不错,但它似乎Function.identity()不是i -> i可能会节省一些内存按照这个相关的答案


小智 5

通用方法

public static <K, V> Map<K, V> listAsMap(Collection<V> sourceList, ListToMapConverter<K, V> converter) {
    Map<K, V> newMap = new HashMap<K, V>();
    for (V item : sourceList) {
        newMap.put( converter.getKey(item), item );
    }
    return newMap;
}

public static interface ListToMapConverter<K, V> {
    public K getKey(V item);
}
Run Code Online (Sandbox Code Playgroud)


Ank*_*rma 5

使用 java-8 流

Map<Integer, String> map = results.stream().collect(Collectors.toMap(e -> ((Integer) e[0]), e -> (String) e[1]));
Run Code Online (Sandbox Code Playgroud)