【问题标题】:How to make a java hashmap containing list?如何制作包含列表的java hashmap?
【发布时间】:2014-08-01 02:58:56
【问题描述】:
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

import mainak.faisal;
import mainak.pulkit;

public class StartingPoint {

    public static void main( String trav[] ) {
        final Map<String, List<String>> paramMap = new HashMap<>();
        List<String> list1 = new ArrayList<String>();
        list1.add("1");
        paramMap.put("segment", list1);
        list1.clear();
        list1.add("2");
        paramMap.put("subDepartment", list1);
        list1.clear();
        list1.add("3");
        paramMap.put("officerTitle", list1);

        for( Map.Entry<String, List<String>> entry : paramMap.entrySet() ) {
            String key = entry.getKey();
            System.out.println("ACTIONKEY"+"------"+key);

            for (String value : entry.getValue()) {
                System.out.println("ACTIONVALUE-----"+value);
            }
        }
    }
}

预期输出:

ACTIONKEY------segment
ACTIONVALUE-----1
ACTIONKEY------subDepartment
ACTIONVALUE-----2
ACTIONKEY------officerTitle
ACTIONVALUE-----3

但它的表现:

ACTIONKEY------segment
ACTIONVALUE-----3
ACTIONKEY------subDepartment
ACTIONVALUE-----3
ACTIONKEY------officerTitle
ACTIONVALUE-----3

为什么会这样?如何在不制作不同列表的情况下达到预期的效果?

【问题讨论】:

  • 3 个键的值都相同(即list1

标签: java list arraylist map hashmap


【解决方案1】:

当您在 java 中传递对象时,实际上传递的是该对象的引用,并且您添加的所有项目都指向与 JB Nizet 在他的回答中解释的相同的列表对象。以下是您可以做的事情:

  1. 每次添加到 Hashmap 对象时都会创建一个新列表。
  2. 使用 Google Guava 集合,例如:

     Multimap<String, String> multiMap = ArrayListMultimap.create();
    
     // put values into map for segment
    
     multiMap.put("segment", "1");
     multiMap.put("segment", "100");
    
     // put values into map for subDepartment
    
     multiMap.put("subDepartment", "2");
     multiMap.put("subDepartment", "200");
    
     // put values into map for officerTitle
    
     multiMap.put("officerTitle", "3");
     multiMap.put("officerTitle", "300");
    
  3. 或使用 Apache Commons Collection,例如:

     // create multimap to store key and values
    
     MultiMap multiMap = new MultiValueMap();
    
     // put values into map for segment
    
     multiMap.put("segment", "1");
     multiMap.put("segment", "100");
    
     // put values into map for subDepartment
    
     multiMap.put("subDepartment", "2");
     multiMap.put("subDepartment", "200");
    
     // put values into map for officerTitle
    
     multiMap.put("officerTitle", "3");
     multiMap.put("officerTitle", "300");
    

所有都会给你正确的输出。 !

【讨论】:

    【解决方案2】:

    您可以每次创建新列表并为其添加价值值,然后放入地图中。

    像这样..

    Map> map = new HashMap>();

        // create list one and store values
        List<String> valSetOne = new ArrayList<String>();
        valSetOne.add("1");
        //valSetOne.add("Aeroplane");
    
        // create list two and store values
        List<String> valSetTwo = new ArrayList<String>();
        valSetTwo.add("2");
       // valSetTwo.add("Banana");
    
        // create list three and store values
        List<String> valSetThree = new ArrayList<String>();
        valSetThree.add("3");
        //valSetThree.add("Car");
    
        // put values into map
        map.put("A", valSetOne);
        map.put("B", valSetTwo);
        map.put("C", valSetThree);
    
    
        for (Map.Entry<String, List<String>> entry : map.entrySet()) {
            String key = entry.getKey();
            List<String> values = entry.getValue();
            System.out.println("Key = " + key);
            System.out.println("Values = " + values );
        }
    }
    

    【讨论】:

      【解决方案3】:

      在放入HashMap之前需要先创建一个列表,

         public static void main(String trav[]){
              final Map<String, List<String>> paramMap = new HashMap<>();
              paramMap.put("segment", Lists.newArrayList("1"));
              paramMap.put("subDepartment", Lists.newArrayList("2"));
              paramMap.put("officerTitle", Lists.newArrayList("3"));
              for(Map.Entry<String, List<String>> entry : paramMap.entrySet()) {
                  String key = entry.getKey();
                  System.out.println("ACTIONKEY"+"------"+key);
                  for (String value : entry.getValue()) {
                      System.out.println("ACTIONVALUE-----"+value);
                  }
          }
      

      【讨论】:

      • 为什么要创建并清除list1? Guava 真的需要创建列表吗? OP 不使用 Guava。
      • 但是你还在使用 Guava。
      • @JBNizet 我使用 Guava 来减少代码。是的,我同意 OP 不使用 Guava 库,但让他探索这种创建列表并将值一次性添加到列表的方式..
      【解决方案4】:

      那是因为您仅将 List 对象的一个​​实例引用到 HashMap。

      当对 List 的引用发生变化时,HashMap 的值也会发生变化。

      你的情况

          list1.add("1");
          paramMap.put("segment", list1);
          list1.clear();
          list1.add("2");
          paramMap.put("subDepartment", list1);
          list1.clear();
          list1.add("3");
      

      您清除后添加到列表中的最后一个值将是您HashMap中所有数据的值

      解决方案:

      每次添加到 HashMap 时创建一个新的 List 实例

      【讨论】:

        【解决方案5】:

        每次要放入地图时,您都必须创建一个新列表。这是因为 map 正在检查列表的引用,并且您正在插入具有相同引用的列表,并且 map 不会存储重复的键,所以基本上它会使用最后一个给定的列表值更新条目。

        【讨论】:

          【解决方案6】:

          如果您希望地图中有 3 个不同的列表,则需要创建 3 个列表。仅创建一个列表将导致地图包含对同一列表的 3 个引用,其中包含您在上一步中存储在列表中的内容:

          segment ---------
                           \
          subDepartment----  [3]
                           /
          officerTitle ----
          

          你想要的是

          segment --------- [1]
          
          subDepartment---- [2]
          
          officerTitle ---- [3]
          

          所以你需要 3 个不同的列表。了解将列表放入地图不会创建列表的副本。它只存储对作为参数传递的列表的引用(如果您愿意,可以是指针)。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2022-06-10
            • 1970-01-01
            • 2015-10-31
            • 2014-08-04
            相关资源
            最近更新 更多