【问题标题】:Java LinkedHashMap: what's the difference in these two?Java LinkedHashMap:这两者有什么区别?
【发布时间】:2010-03-01 19:03:17
【问题描述】:

编辑:可以从http://gitorious.org/scheator 找到整个代码和数据库创建脚本。数据库脚本在 Schema/ 中。

我有以下 Java 代码:

在抽象类中定义为 LinkedHashMap

LinkedHashMap<Object, Data> list;

一个像这样初始化这个列表的后代类:

list = new LinkedHashMap<Integer, Data>();

我添加这样的项目:

    String id = rs.getString(FIELDS[0]);
    String name = rs.getString(FIELDS[1]);
    Data team = new Data(Integer.parseInt(id.trim()), name);
    list.put(id, team);

现在当我这样做时:

    System.err.println("delete() count: " + list.size());

    System.err.println("delete() key value " + key);
    Data obj;
    obj = (Data)list.remove(key);
    deletedList.put(key, obj);
    System.err.println("delete() count: " + list.size());

没有从列表中删除,即第一个和最后一个打印打印相同的 size()。密钥也是正确的(我已验证该 id 有一个项目)。

但是,这是我的问题,如果我添加这样的值:

    Integer id = rs.getInt(FIELDS[0]);
    String name = rs.getString(FIELDS[1]);
    Data team = new Data(id, name);
    list.put(id, team);

代码有效! parseInt() 不应该产生与 getInt() 类似的键吗?为什么第二个版本可以用,第一个不行?我花了一个小时调试这个,直到找到原因,我仍然无法弄清楚原因。

【问题讨论】:

  • key变量的类型是什么?
  • 什么是 rs ?它是什么样的物体?
  • 在您的第一个示例中,您没有显示要添加的项目。你确定有一个带有那个键的项目吗?
  • @splix:整数。 @Eric:一个记录集。 @Robin:除了项目添加到地图的方式之外,项目完全相同。
  • @Eric rs 看起来将是来自数据库的 ResultSet

标签: java linkedhashmap


【解决方案1】:

第一个例子:

String id = rs.getString(FIELDS[0]);

第二个例子:

Integer id = rs.getInt(FIELDS[0]);

我不能肯定地说,因为我看不到其余代码,但如果 key 变量在此调用中是一个整数:

obj = (Data)list.remove(key);

那么只有在使用整数将对象放入地图时,删除才会起作用,这就是为什么当您调用 put 方法时它仅在 id 为整数时才起作用。字符串“123”不等于整数 123。

另外我假设您在第一个示例中错过了一行,但没有调用 list.put(id, team) 但这也可能是您问题的根源

【讨论】:

  • 是的,我不小心遗漏了第一个示例中的 put()。和第二个一模一样。
【解决方案2】:

应该没有区别,但是从你的例子中有很多东西不清楚:

  • deletedList 不引用 list 对象
  • 您的数据库中正在使用的记录在这两种情况下都是相同的(也许在第一种情况下,正在使用 Map 中已经存在的不同 int)

自动装箱也可能使问题复杂化。将第二个示例中的 Integer id 替换为 int id 以将相同的参数传递给您的 Data 构造函数。

也许您可以发布完整的代码,以便我们可以准确地重现场景?


更新

您在原始代码中使用字符串值作为键。然后,您的 remove(key) 方法中有一个 Object 键,因此我希望您此时将一个 Integer 传递给该方法。字符串不会匹配整数作为键,这就解释了为什么您的删除不起作用。

如果您使用泛型来指定您的 HashMap(LinkedHashMap&lt;Integer, Team&gt; 而不是 &lt;Object, Team&gt;),则不会发生这种错误 - 编译器会说类似

The method put(Integer, Object) in the type HashMap&lt;Integer,Object&gt; is not applicable for the arguments (String, String)

【讨论】:

  • 完整的代码是几百行代码。只是我提到的两个类超过 300 行,它们远非一个可运行的示例。您可以从 gitorious.org/scheator 获取当前处于婴儿期的整个代码。提交 2b34bde 有非工作代码,而提交 c64daed3 已修复。有问题的文件位于 src/ScheatorDb:AbstractDb.java 和 Teams.java。
  • 哦,如果没有 MySQL 数据库,您仍然无法运行。我尚未将用于创建数据库的 SQL 命令添加到存储库中。
  • 正在调查。真的没有时间,但无法抗拒谜题!
  • 我添加了数据库架构以防您想运行它。警告:尽管我已经编写了 20 多年的代码,但这是我的第一个 Java 应用程序,并且正在开发中以达到顶峰,所以请期待糟糕的代码!
  • 我希望能够为 DbObject 类的后代使用除整数以外的其他键类型。不过,它在 Team 类中被初始化为
【解决方案3】:

Yanamon 是对的。看the diff就很清楚了:

             while (rs.next()) {
-                String id = rs.getString(FIELDS[0]);
+                Integer id = rs.getInt(FIELDS[0]);
                 String name = rs.getString(FIELDS[1]);
-                Data team = new Data(Integer.parseInt(id.trim()), name);
+                Data team = new Data(id, name);
                 list.put(id, team);

请注意,在原始版本中,一个 int(自动装箱为 Integer)被传递到 Data 构造函数中。但是被放入的 id 仍然是一个字符串。

【讨论】:

  • 这是正确的答案。您可以查看代码多长时间而看不到这样的简单问题,这太荒谬了。我已经将 id 固定为 Integer 并使用 getInt() 获取它,这是一种更好的方法。
【解决方案4】:

我的猜测是,在第二种情况下,您将其显式转换为整数

Integer id = rs.getInt(FIELDS[0]);

在第一种情况下,它仍然是一个 int

Integer.parseInt(id.trim())

来自 parseInt 的 javadoc

static int  parseInt(String s) 
Parses the string argument as a signed decimal integer.

【讨论】:

  • 是的...,但它会在添加到地图时自动装箱为整数。 Integer hashCode 和 equals 方法只使用 int 原始值。所以应该没关系。
【解决方案5】:

如果我是你,我会使用调试器检查 LinkedHashMap 的内容,在你的 put 之前和之后以及在你 remove 之前和之后。进入remove() 方法(源代码是JDK 的一部分),看看它在做什么。奇怪的是您的代码没有正确添加或删除对象。在这里很难看到,因为代码示例不完整。

至于rs.getInt()Integer.parseInt(),第一个是特定于数据库供应商的(我假设rs 是ResultSet),因此它们的行为可能不同。但是,一旦创建了 Integer 键(您可以使用调试器验证这一点),它对于 HashMap 或 LinkedHashMap 的目的应该是等效的。但是您的代码示例使事情变得更加复杂;您使用的是rs.getString(),然后是Integer.parseInt()。虽然如果发生这种情况我会感到惊讶,但数据库驱动程序可能会将 id 列格式化为混淆parseInt() 的字符串。对我来说,只做rs.getInt() 更具可读性。

【讨论】:

    猜你喜欢
    • 2011-04-06
    • 1970-01-01
    • 2013-02-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-31
    相关资源
    最近更新 更多