从 hashmap 存储和检索 ArrayList 值

Posted

技术标签:

【中文标题】从 hashmap 存储和检索 ArrayList 值【英文标题】:Storing and Retrieving ArrayList values from hashmap 【发布时间】:2013-11-01 17:21:16 【问题描述】:

我有以下类型的哈希图

HashMap<String,ArrayList<Integer>> map=new HashMap<String,ArrayList<Integer>>();    

存储的值是这样的:

mango | 0,4,8,9,12
apple | 2,3
grapes| 1,7
peach | 5,6,11

我想使用迭代器或任何其他方式以最少的代码行存储和获取这些整数。我该怎么做?

编辑 1

数字是随机添加的(不是一起),因为键与相应的行匹配。

编辑 2

如何在添加时指向数组列表?

map.put(string,number); 行中添加新号码18 时出错

【问题讨论】:

【参考方案1】:

方法一:使用 putIfAbsent

    Map<String, List<Integer>> map = new HashMap();
    map.putIfAbsent("mango",new ArrayList<>());
    map.get("mango").add(5);

方法 2:检查 Map 中存在的键

    Map<String, List<Integer>> map = new HashMap();
    if(! map.containsKey("mango")
          map.put("mango",new ArrayList<>());
    
    List<Integer> list = map.get("mango");
    list.add(3);
  
    

方法3:使用getOrDefault

    Map<String, List<Integer>> map = new HashMap();
    List<Integer> list = map.getOrDefault("mango",new ArrayList<>());
    list.add(4)

      
  

【讨论】:

【参考方案2】:

在 Java 中向多映射(列表映射)添加条目的现代方式(截至 2020 年)是:

map.computeIfAbsent("apple", k -> new ArrayList<>()).add(2);
map.computeIfAbsent("apple", k -> new ArrayList<>()).add(3);

根据Map.computeIfAbsent docs:

如果指定的键尚未与值关联(或映射到null),则尝试使用给定的映射函数计算其值并将其输入到此映射中,除非null

返回: the current (existing or computed) value associated with the specified key, or null if the computed value is null

迭代列表映射最惯用的方法是使用Map.forEachIterable.forEach

map.forEach((k, l) -> l.forEach(v -> /* use k and v here */));

或者,如其他答案所示,传统的 for 循环:

for (Map.Entry<String, List<Integer>> e : map.entrySet()) 
    String k = e.getKey();
    for (Integer v : e.getValue()) 
        /* use k and v here */
    

【讨论】:

【参考方案3】:

我们的变量:

Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();

存储:

map.put("mango", new ArrayList<Integer>(Arrays.asList(0, 4, 8, 9, 12)));

要添加数字一和一,您可以执行以下操作:

String key = "mango";
int number = 42;
if (map.get(key) == null) 
    map.put(key, new ArrayList<Integer>());

map.get(key).add(number);

在 Java 8 中,如果列表不存在,您可以使用 putIfAbsent 添加列表:

map.putIfAbsent(key, new ArrayList<Integer>());
map.get(key).add(number);

使用map.entrySet() 方法进行迭代:

for (Entry<String, List<Integer>> ee : map.entrySet()) 
    String key = ee.getKey();
    List<Integer> values = ee.getValue();
    // TODO: Do something.

【讨论】:

:ee.getValue() 返回什么?我想是一个 ArrayList。所以我想我需要一个临时 arralist。是这样吗? @InsaneCoder 是的,它返回一个 ArrayList(整数)。你是否需要一个临时的 ArrayList 取决于你想用它做什么。您可以多次调用 ee.getValue 仍然得到相同的 ArrayList。【参考方案4】:

您可以尝试使用 MultiMap 代替 HashMap

初始化它需要更少的代码行。添加和检索值也会使其更短。

Map<String, List<Integer>> map = new HashMap<String, List<Integer>>();

会变成:

Multimap<String, Integer> multiMap = ArrayListMultimap.create();

您可以查看此链接:http://java.dzone.com/articles/hashmap-%E2%80%93-single-key-and

【讨论】:

【参考方案5】:

你可以这样使用(虽然随机数生成器逻辑不合格)

public class WorkSheet 
    HashMap<String,ArrayList<Integer>> map = new HashMap<String,ArrayList<Integer>>();

public static void main(String args[]) 
    WorkSheet test = new WorkSheet();
    test.inputData("mango", 5);
    test.inputData("apple", 2);
    test.inputData("grapes", 2);
    test.inputData("peach", 3);
    test.displayData();


public void displayData()
    for (Entry<String, ArrayList<Integer>> entry : map.entrySet()) 
        System.out.print(entry.getKey()+" | ");
        for(int fruitNo : entry.getValue())
            System.out.print(fruitNo+" ");
        
        System.out.println();
    

public void inputData(String name ,int number) 
    Random rndData = new Random();
    ArrayList<Integer> fruit = new ArrayList<Integer>();
    for(int i=0 ; i<number ; i++)
        fruit.add(rndData.nextInt(10));
    
    map.put(name, fruit);


输出

grapes | 7 5 
apple | 9 5 
peach | 5 5 8 
mango | 4 7 1 5 5 

【讨论】:

【参考方案6】:
Iterator it = map.entrySet().iterator();
while (it.hasNext()) 
     Map.Entry pairs = (Map.Entry)it.next();

     if(pairs.getKey().equals("mango"))
     
        map.put(pairs.getKey(), pairs.getValue().add(18));
     

     else if(!map.containsKey("mango"))
     
        List<Integer> ints = new ArrayList<Integer>();
        ints.add(18);
        map.put("mango",ints);
     

     it.remove(); // avoids a ConcurrentModificationException

编辑: 所以在while里面试试这个:

map.put(pairs.getKey(), pairs.getValue().add(number))

您收到错误是因为您尝试将整数放入值中,而预期为ArrayList

编辑 2: 然后将以下内容放入您的 while 循环中:

if(pairs.getKey().equals("mango"))

    map.put(pairs.getKey(), pairs.getValue().add(18));


else if(!map.containsKey("mango"))

     List<Integer> ints = new ArrayList<Integer>();
     ints.add(18);
     map.put("mango",ints);
 

编辑 3: 通过阅读您的要求,我认为您可能不需要循环。您可能只想检查映射是否包含键 mango,如果确实添加了 18,否则在映射中使用键 mango 和值 18 创建一个新条目。

所以你可能只需要以下内容,没有循环:

if(map.containsKey("mango"))

    map.put("mango", map.get("mango).add(18));


else

    List<Integer> ints = new ArrayList<Integer>();
    ints.add(18);
    map.put("mango", ints);

【讨论】:

如何将整数添加到特定键。添加时map.put(string,number); 出现错误。 我没有 IDE 来测试代码,所以可能存在语法错误。 好的!!我会检查的。请发布它 :实际上我想要一些“如果有一个键'芒果'添加18否则创建键'芒果'并添加18”。我认为这段代码不会这样做 @InsaneCoder 请参阅编辑 2【参考方案7】:

一次性获取所有内容 =

List<Integer> list = null;

if(map!= null) 
 
  list = new ArrayList<Integer>(map.values()); 

用于存储 =

if(map!= null) 
 
  list = map.get(keyString); 
   if(list == null)
    
         list = new ArrayList<Integer>();
    
  list.add(value);
  map.put(keyString,list);

【讨论】:

【参考方案8】:
for (Map.Entry<String, ArrayList<Integer>> entry : map.entrySet()) 
 System.out.println( entry.getKey());     
 System.out.println( entry.getValue());//Returns the list of values

【讨论】:

以上是关于从 hashmap 存储和检索 ArrayList 值的主要内容,如果未能解决你的问题,请参考以下文章

面试重点之从源码分析HashMap和ArrayList在存储扩容等方面的区别

如何从android中的firebase中检索List对象

array,vertor,arraylist,hashable,hashmap等几个易混淆概念的区别

把一个ArrayList中的值,存储到一个HashMap中

例外:从意图存储ArrayList时“无法转换为java.util.ArrayList”

集合-ArrayList与HashMap的区别