【问题标题】:Attempting to iterate HashMap with a for-loop yields null?尝试使用 for 循环迭代 HashMap 会产生 null 吗?
【发布时间】:2016-04-12 21:30:09
【问题描述】:

这是Data.ListGroupedProducts的声明

public static HashMap<String, HashMap<String, WrapperProduct>> ListGroupedProducts = new HashMap<>();

我这样做的原因是用新的/更新的对象替换集合深处的对象。我在尝试 get HashMap 中需要的集合时继续获得 null

这是我的调试截图,鼠标悬停在Data.ListGroupedProducts

红色箭头是我试图达到的......不可能用for循环迭代它吗?

更新

感谢Boann 的回答,我能够解决这个问题。这是完整的方法,以防有人犯我在尝试使用 for 循环迭代 KeySet 时犯的同样错误!

    //Product coming in, has the latest updates and this will be used
    //to update the product deep in Data.ListGroupedProducts.
    public boolean UpdateListGroupProducts(ManifestProduct product) {

        for(int a=0; a < Data.SelectedInvoice.size(); a++){
            String invoiceNumber = Data.SelectedInvoice.get(a).ID;

            if(Data.ListGroupedProducts.containsKey(invoiceNumber)){
                //Iterate over each key using a keyset, we will then use the key on the for-loop
                //to retrieve the inner object and manipulate it as needed.
                for(String key: Data.ListGroupedProducts.get(invoiceNumber).keySet()){
                    for(int x=0; x < Data.ListGroupedProducts.get(invoiceNumber).get(key).ProductList.size(); x++){
                        String productID = Data.ListGroupedProducts.get(invoiceNumber).get(key).ProductList.get(x).ID;
                        String productItemID = Data.ListGroupedProducts.get(invoiceNumber).get(key).ProductList.get(x).ITEMID;

                        if(product.ID.equals(productID) && product.ITEMID.equals(productItemID)){
                            //Use ArrayList's set method to replace a position in the array with a new instance.
                            Data.ListGroupedProducts.get(invoiceNumber).get(key).ProductList.set(x, product);
                            return true;
                        }
                    }//Inner For
                }//Outer For
            }
        }
        return false;
   }

【问题讨论】:

  • 你能把这个减少到minimal reproducible example吗?请遵循 Java 命名约定。如果您要重用Data.ListGroupedProducts.get(invoiceNumber) 的值,请将其提取到一个短名称变量并重用它。使代码更具可读性。
  • a &lt;= Data.SelectedInvoice.size()-1 通常写成a &lt; Data.SelectedInvoice.size()
  • 这没有多大意义。你打电话给containsKeyData.SelectedInvoice.get(a).ID,然后你打电话给getData.SelectedInvoice.get(a).ID.toString()。他们不应该是一样的吗?
  • @PaulBoddington Java 新手--containsKey 返回值?以为我只是在检查,这就是为什么我后来做了get ..
  • containsKey 检查键是否在映射中并返回truefalse。这与您应该传递给get 的内容相同。您是否尝试将.toString() 添加到您传递给containsKey() 的内容中?

标签: java for-loop hashmap


【解决方案1】:

您不能使用for (int x = 0; x &lt; size; x++) 样式的循环来迭代HashMap。映射中的键值对没有关联的数字索引或特定顺序。因此,在地图上调用get(x) 会尝试查找键0 的值。但是没有这样的映射,因为那个映射的键类型是String,而真正的键是"FREEZER"。由于没有与键0 的映射,get 返回null

要迭代作为内部HashMap 值的WrapperProduct 实例,请将for(int x...) 循环替换为:

for (WrapperProduct w : Data.ListGroupedProducts.get(invoiceNumber).values()) {
    System.out.println(w);
}

This page 解释了更多关于迭代地图的方法。

【讨论】:

  • 我意识到我的问题,我知道我可以使用 foreach 就好了,但没有因为我认为我无法替换内部 HashMap 中的内部 obj使用该obj 的新版本。我错了,感谢您链接的页面和解释。
  • 如果它不是不可变的,您可以很好地改变地图中对象的属性。如果您想用实际不同的对象实例替换它,那么您将需要通过键值对或键来迭代映射,以便在循环中您可以访问要在映射中使用的键 put 调用.
  • 谢谢,我将尝试使用键值对,看看如果我目前的实现不起作用,效果如何。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-08-18
  • 2015-11-11
  • 1970-01-01
  • 1970-01-01
  • 2019-10-29
  • 2019-07-28
  • 1970-01-01
相关资源
最近更新 更多