4

编辑:整个代码和数据库创建脚本可以从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() 类似的键吗?为什么第二个版本可以用,第一个不行?我花了一个小时调试这个,直到我找到原因,我仍然无法弄清楚原因。

4

5 回答 5

2

应该没有区别,但是您的示例中有许多不清楚的地方:

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

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

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


更新

您在原始代码中使用字符串值作为键。然后,您的 remove(key) 方法中有一个 Object 键,因此我希望您此时将一个 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)

于 2010-03-01T19:19:21.327 回答
2

第一个例子:

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

第二个例子:

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

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

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

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

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

于 2010-03-01T19:29:10.017 回答
1

亚那蒙是对的。当您查看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 仍然是一个字符串。

于 2010-03-01T19:35:10.543 回答
0

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

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.
于 2010-03-01T19:14:31.680 回答
0

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

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

于 2010-03-01T19:23:58.907 回答