使用HashMap使用相同的键更新多个值的问题

时间:2016-11-10 19:16:03

标签: java hashmap key-value

我遇到一个问题,其中一个键/值对正在正确更新,但具有相同键的其他值未得到更新。我正在使用一个HashMap,它包含一个字符串列表(Item Nbr)作为键,值存储为一个字符串列表(PO Nbr),因此在这方面它基本上是一对多的。下面是我实现这个HashMap的代码,但我只是卡住了。任何帮助将不胜感激。

public void process(List<PoBean> excelData,List<String> errors) throws CustomException 
{       
    Map<String,ArrayList<String>> poNbrItemNbrMap = new HashMap<String, ArrayList<String>>();
    ArrayList<String> poNbrList = new ArrayList<String>();

    int recordCount = excelData.size();

    for(PoBean bean : excelData)
    {                                       
        if(rowValidator.validate(bean, errors))
        {
            if (!newErrorInRow(errors)) 
            {
                poNbrList.add(bean.getPoId());
                poNbrItemNbrMap.put(bean.getItemNbr(),bean.getPoId());
            }           
        }
    }

    List<DutyFees> dutyFeesTempDAO = myService.getAssocIdByPOAndItemNbr(new ArrayList<String>(poNbrItemNbrMap.keySet()),new ArrayList<String>(poNbrItemNbrMap.values()));           

    for(DutyFees duty : dutyFeesTempDAO)
    {   
        Double dutyFees = new Double(0);
        if(poNbrItemNbrMap.containsKey(duty.getItemNbr()) && poNbrItemNbrMap.containsValue(duty.getPoId())) 
        {               
            for(PoBean dutyBean : excelData)
            {
                if(duty.getPoId().equals(dutyBean.getPoId()) && duty.getItemNbr().equals(dutyBean.getItemNbr()))
                {
                    dutyFees = new Double(dutyBean.getDutyFees());
                    break;
                }
            }
            Boolean result = myService.updateDutyFeesByAssocID(duty.getAssocId(), dutyFees);            
        }                               
    }       
}

2 个答案:

答案 0 :(得分:1)

你说你想要一对多,但你的代码有一对一

HashMap<String,String> poNbrItemNbrMap = new HashMap<String,String>();

一个字符串值的一个字符串键

斜体部分与您问题中的粗体部分形成对比。

  

我正在使用一个HashMap,它由一个字符串列表(Item Nbr)组成   键和值存储为字符串列表(PO Nbr), 所以它是   在这方面基本上是一对多。

斜体意味着许多人。 大胆意味着一对多。

无论如何,让我给你两个实现。

public class Test {
  public static void main(String[] args) {

    System.out.println("= One to Many =");
    Map<String, List<String>> stringListMap = new HashMap<>();
    String key = "list of 4 strings";
    List<String> valuesList = Arrays.asList("one","two","three","four");
    stringListMap.put(key,valuesList);
    stringListMap.forEach((strings, strings2) -> System.out.println(strings.toString() + strings2.toString()));

    System.out.println("= Many to Many =");
    Map<List<String>, List<String>> listListMap = new HashMap<>();
    List<String> keys = Arrays.asList("1","2","3","4");
    List<String> values = Arrays.asList("one","two","three","four");
    listListMap.put(keys,values);
    listListMap.forEach((strings, strings2) -> System.out.println(strings.toString() + strings2.toString()));


  }
}

编辑回复您的评论。 不确定你在评论中的意思,但我确实看到了几个问题。首先,当您放入地图时,您正在放置看似项目编号和po ​​id的内容,因此它们似乎都是单个字符串类型而不是ArrayList。所以我甚至不确定你是如何编译它的。除非你的getPoId实际上是getPoIds并返回一个列表。我在谈论这一行

poNbrItemNbrMap.put(bean.getItemNbr(),bean.getPoId());

现在关于

new ArrayList<String>(poNbrItemNbrMap.values())

你不能像那样初始化数组列表。

我不知道getAssocIdByPoAndItemNbr函数的签名是什么,所以无法提出答案。但是,如果您只想发送映射值,那么直接发送它为什么将它作为构造函数参数放入新的ArrayList&lt;&gt;()?

答案 1 :(得分:0)

process第一部分的目的很明确:将PoBean个对象列表转换为Map<String, List<String>>,将对象按itemNbr分组到列表中。以下是代码:

// One-to-many relationship requires the value to be a List
// Better not say ArrayList here because then you put unnecessary
// Restrictions on the code.
Map<String, List<String>> poNbrItemNbrMap = new HashMap<>();

for(PoBean bean : excelData)
{                                       
    if(rowValidator.validate(bean, errors))
    {
        if (!newErrorInRow(errors)) 
        {
            String key = bean.getItemNbr();
            List<String> value = poNbrItemNbrMap.get(key);
            if (value == null) {
                // This is first time we see this item nbr,
                // Create a new list to hold the values
                value = new ArrayList<>();
                poNbrItemNbrMap.put(key, value);
            }
            // Just add the value to the list
            value.add(bean.getPoId());
        }           
    }
}

现在第二部分令人困惑,尤其是这一行:

List<DutyFees> dutyFeesTempDAO = myService.getAssocIdByPOAndItemNbr(new ArrayList<String>(poNbrItemNbrMap.keySet()),new ArrayList<String>(poNbrItemNbrMap.values()));

第一个参数几乎没有意义,它传递的密钥为List;没关系。第二个参数无法编译,因为您需要new ArrayList<List<String>>(poNbrItemNbrMap.values())。是的,您需要一个字符串列表列表。但这仅仅是个开始。 通过执行此操作,您基本上删除了键和值之间的关系,getAssocIdByPOAndItemNbr方法无法再将关键字及其各自的值关联起来。它不能假设键中的第一项映射到值中的第一项。这意味着我们在第一部分做的任何事都没用。