【问题标题】:Add elements to a HashMap containing an ArrayList将元素添加到包含 ArrayList 的 HashMap
【发布时间】:2019-02-17 00:15:30
【问题描述】:

这个简单的方法应该是向 HashMap 添加元素。这些元素是从 txt 文件中读取的,我已经对其进行了测试,并且该区域的所有内容都运行良好。当我打印地图中的值时会出现问题。因此,我认为添加它们时可能会出现一些问题。

txt文件的内容是

SW: (scores, 90); (scores, 91); (scores, 92);

权限为“SW”,属性为“(scores, 90)... (scores, 92)”。这些是以下方法中使用的元素。

public Map<Permissions, ArrayList<Attributes>> paMap; 

public void addMap(Permissions per, Attributes att) {
    if(paMap.containsKey(per)) {
        paMap.get(per).add(att);            
    }
    else{
        ArrayList<Attributes> attList = new ArrayList<Attributes>();
        attList.add(att);
        paMap.put(per, attList);
    }
}

 //Attributes contain variables (Scores) and values(90-93), that is just for printing

public void printMap() {
    ArrayList<Attributes> list;

    for(Permissions p: paMap.keySet()) {
        list = paMap.get(p);
        System.out.print(p.name + ": ");

        for(Attributes l: list) {
            System.out.print("<" + l.variable +", " + l.value + ">; ");
        }
        System.out.println();
    }

当我打印地图时,我希望得到与 txt 文件中完全相同的内容,但我却得到了

SW:(得分,92); (得分,92); (得分,92)

即使我从 addMap 方法中删除 paMap.get(per).add(att) 行,我最终也会得到 SW: (scores, 92);

另外,我已经测试了是否正确调用了 for 循环。

因此,我对 ArrayList 上的属性如何更新以及正确的做法感到困惑。您是否发现我添加或打印值的方式有任何错误?

感谢您的帮助

【问题讨论】:

  • 向我们展示您是如何读取 txt 文件并调用 addMap(...) 方法的。
  • @Luis Claramunt 您能否也为Permissions 类添加您的代码?如答案中所述 - 重要的是使 Permissions 不可变并正确定义 equals and hashCode
  • 小心使用可变对象作为映射键

标签: java arraylist hashmap


【解决方案1】:

我不知道 read 方法看起来如何,但似乎你一直在添加相同的属性,所以也许在 read 函数中你不是创建新属性而是一直使用相同的对象,只是在这个上调用集合,所以在数组 lsit 的末尾是相同的对象添加了 3 次

顺便说一句: 方法 addmap 也可以替换为:

paMap.computeIfAbsent(per,x->new ArrayList<Attributes>()).add(att);

如果您使用的是 java8 及以上版本 ;)

【讨论】:

  • x -&gt; new ArrayList&lt;&gt;()应该够用了,这里可以放心使用钻石算子。
  • computeIfAbsent() 的建议很棒!它确实与整个addMap 方法一样。不幸的是,它完全一样,所以它仍然打印错误的输出。因此,我认为错误必须在其他地方。谢谢!
【解决方案2】:

几个建议:

  • Map 声明中使用接口:
public Map<Permissions, List<Attributes>> paMap; 
  • 为了用作Map 中的键,请确保Permissions 是 不可变并且正确定义了equalshashCode

所以,假设 Permissions 只有 1 个字符串字段,它应该看起来像这样:

public final class Permissions {
  private final String permission;
  public Permissions(String permission) {
    this.permission = permission;
  }
  public String getPermission() {
    return this.permission;
  }
  @Override
  public boolean equals(Object o) {
    if (this == o) {
      return true;
    }
    if (o == null || getClass() != o.getClass()) {
      return false;
    }
    Permissions that= (Permissions ) o;
    return Objects.equals(this.permission, that.permission);
  }
  @Override
  public int hashCode() {
    return Objects.hash(this.permission);
  }
}
  • 尝试另一种实现printMap 方法。例如,使用 Java 8:
  private void printMap() {
    paMap.entrySet().stream().map(this::format).forEach(System.out::println);
  }
  private String format(Map.Entry<Permissions, List<Attributes>> entry) {
    String key = formatPermissions(entry.getKey());
    String value = formatAttributes(entry.getValue());
    return String.format("%s: %s", key, value);
  }
  private String formatPermissions(Permissions permissions) {
    return permissions.name;
  }
  private String formatAttributes(List<Attributes> attributes) {
    return attributes.stream()
            .map(attr -> String.format("(%s, %s)", attr.variable, attr.value))
            .collect(Collectors.joining("; "));
  }

【讨论】:

  • 感谢您的建议,我将更多地研究使用不可变对象作为键。此外,addMap 中的 for 循环也没有损坏。这是我测试的第一件事,它只在第一次调用 addMap 函数时到达 else 语句。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多