Java LinkedHashMap:这两者有什么区别?

时间:2010-03-01 19:03:17

标签: java linkedhashmap

编辑:可以从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());

没有从列表中删除任何内容,即第一个和最后一个打印件打印相同的大小()。密钥也是正确的(我已经验证了该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()的键吗?为什么第二个版本有效,但第一个版本没有?我花了一个小时调试这个,直到找到原因,我仍然无法弄清楚原因。

5 个答案:

答案 0 :(得分:2)

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

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

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

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


更新

您在原始代码中使用字符串值作为键。然后在remove(key)方法中有一个Object键,所以我希望你现在将Integer传递给方法。 String不会将Integer与键匹配,这就解释了为什么删除无效。

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

The method put(Integer, Object) in the type HashMap<Integer,Object> is not applicable for the arguments (String, String)

答案 1 :(得分:2)

第一个例子:

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

第二个例子:

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

我不能肯定地说,因为我看不到剩下的代码,但是如果key变量是这个调用中的整数:

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

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

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

答案 2 :(得分:1)

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仍然是一个字符串。

答案 3 :(得分:0)

我的猜测是,在第二种情况下,你将它明确地转换为整数

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.

答案 4 :(得分:0)

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

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