-3

这是一个非常简单的任务,但我觉得我忽略了一些东西。我有多个要添加到 ArrayList 的对象,每个对象都有一个字符串形式的标识名称。我需要能够通过调用字符串名称来查找(交互)ArrayList 中的对象。所以我尝试了这个:

在我的项目类中,我有: private String itemName;

public Item(String name)
{
    itemName = name;
}

所以我可以给它一个名字供用户使用。


然后在与对象交互的类中,我创建了一个 ArrayList:

private ArrayList<Item> items = new ArrayList<Item>();

我首先通过它的实际对象名称将对象添加到arrayList,但我需要能够使用它的字符串名称与它进行交互,所以我尝试了这个:

public void removeItem(String itemName)
{
    for (int i = 0; i < items.size(); i++)
    {
        if (items.get(i).toString() == itemName)
        {
            items.remove(i);
        }
        break;
    }

}

但它不会删除该项目。如果所有这些都令人困惑,那么本质上我正在尝试创建一个可以给 STRING 名称命名的 OBJECT(就像我对上面的项目所做的那样),然后能够将 OBJECT 添加到 ArrayList,然后最终成为能够通过调用 STRING 名称来删除、获取或对 ArrayList 中的 OBJECTS 执行某些操作。我知道我需要遍历 ArrayList,但我实际上无法获取该对象。

谢谢你的帮助。

4

5 回答 5

4

你在这里犯了三个错误:

  • 您正在使用items.get(i).toString()which 不会为您itemName提供Item. 如果你不覆盖一个,它只会给你一个类的字符串表示Item,由Object类的方法返回。toString但是,如果您重写了一个toString方法并itemName从中返回,这可能会起作用。但是,我没有看到。即使您已经覆盖了它,我建议您为您的字段设置gettersetteritemName,并使用它来返回itemName.

  • 您正在使用==运算符比较字符串,这不会给您正确的结果。equals您应该始终使用方法比较字符串。

所以,你if statement应该看起来像:

 if (items.get(i).getName().equals(itemName))
  • 第三个问题是,您正在尝试修改List您正在迭代的内容。这不会成功,并且可能会抛出ConcurrentModificationException. 您应该使用IteratorList迭代中删除元素。

有关这两个问题以及如何解决它们的更多详细信息,请参阅:

此外,您可以考虑在您的 中覆盖equals方法class,然后您可以使用equals方法直接比较您的实例。


现在,已经指出了您的代码的一些逻辑问题,是时候指出一些设计问题了。

鉴于您的要求,您似乎需要使用 a HashMap,而不是 aList存储您的属性的某些自定义类型。您可以创建一个map这样的:

Map<String, Integer> map = new HashMap<String, Integer>();

它将包含itemName到各自的映射Item,然后Item为特定的 itemName 获取就像map.get(itemName).

于 2013-02-12T16:18:56.813 回答
3

听起来您应该Map为此使用 a ,例如java.util.HashMap<String, Item>。该Map接口提供了您正在寻找的那些操作,并且它也是可迭代的。

于 2013-02-12T16:21:14.070 回答
1

向您的对象添加一个 getter 以获取名称,如下所示:

public class Item {
   private final String name; //once given cannot change
   public Item(String name) {
      this.name = name; //yhis.name to distinguish between 2 variabled both called "name"
   }
   public String getName() {
      return name; //this.name not required as no other variable called "name" is in scope
   }
}

那么你可以像这样找到你的项目:

for (Item item : theList) {
   if (item.getName.equals(requiredName)) {
      //got you!
   }
}

一般来说,永远不要将字符串与==. 此外,如果你想从你正在迭代的列表中删除一个项目,你必须使用(旧的)迭代器语法:

Iterator<Item> iter = theList.iterator();
while (iter.hasNext()) {
   Item item = iter.next();
   if (item.getName.equals(requiredName)) {
      //got you!
      iter.remove();
      break; //no need to go over the rest of the list
   }
}

最后,如果您只想按名称查找项目,则列表不是您最好的集合,因为查找项目可能需要遍历整个列表。地图(特别是哈希图)将为您提供此类操作的更好性能。您可以使用名称作为键

于 2013-02-12T16:20:07.163 回答
0

有这个 - 你实现 removeItem 的方式,你也可以直接使用 ArrayList.remove(item.itemName) 来做- 就在你坚持ConcurrentModificationException并重新实现已经存在的东西之前 - 看看图书馆!阅读 ArrayList 的文档!

澄清一下:在 Java 中(并且实际上仅在 Java 中):==表示参考比较。

所以:

String a = "A";
String b = new StringBuilder("A").toString();
if (a == b) // --> false
if (a.equals(b)) // --> true

您也可以考虑使用org.apache.commons.lang.StringUtils.equals - 这对于空指针是安全的。

正如其他人已经指出的那样 -toString只有在正确实现它的情况下 - 方法才能正常工作(在您的情况下返回名称)。By originaltoString返回一个类名和一个 ID。这可能不是您想要的(只需尝试将其打印出来)。

于 2013-02-12T16:29:45.990 回答
0

我的猜测是你 items.get(i).toString() 没有做你认为它做的事情。为什么不使用 items.get(i).name 之类的东西,或者在 Item 对象中为 name 创建 getter 或 setter 并通过 items.get(i).getName() 检索名称

于 2013-02-12T16:19:43.187 回答