13

我已经为我的问题创建了一个简短的示例。我正在匿名创建对象列表并将它们添加到ArrayList. 一旦项目进入,ArrayList我稍后会回来并为列表中的每个对象添加更多信息。如果您不知道其索引,有没有办法从列表中提取特定对象?

我只知道对象的“名称”,但你不能做 alist.get(ObjectName)或任何事情。处理此问题的推荐方法是什么?每次我想检索一个特定对象时,我都不想遍历整个列表。

public class TestCode{

    public static void main (String args []) {
        Cave cave = new Cave();

        // Loop adds several Parties to the cave's party list
        cave.parties.add(new Party("FirstParty")); // all anonymously added
        cave.parties.add(new Party("SecondParty"));
        cave.parties.add(new Party("ThirdParty"));

        // How do I go about setting the 'index' value of SecondParty for example?
    }
}

class Cave {
    ArrayList<Party> parties = new ArrayList<Party>();
}

class Party extends CaveElement{
    int index;

    public Party(String n){
        name = n;
    }

   // getter and setter methods 

    public String toString () {
        return name;
    }
}


class CaveElement {
    String name = "";
    int index = 0;

    public String toString () {
        return name + "" + index;
    }
}
4

7 回答 7

15

鉴于使用List,如果不遍历它,就无法“查找”一个值......

例如...

Cave cave = new Cave();

// Loop adds several Parties to the cave's party list
cave.parties.add(new Party("FirstParty")); // all anonymously added
cave.parties.add(new Party("SecondParty"));
cave.parties.add(new Party("ThirdParty"));

for (Party p : cave.parties) {
    if (p.name.equals("SecondParty") {
        p.index = ...;
        break;
    }
}

现在,这需要时间。如果您要查找的元素位于列表的末尾,则必须在找到匹配项之前迭​​代到列表的末尾。

最好使用Map某种...

所以,如果我们更新Cave看起来像......

class Cave {
    Map<String, Party> parties = new HashMap<String, Party>(25);
}

我们可以做类似...

Cave cave = new Cave();

// Loop adds several Parties to the cave's party list
cave.parties.put("FirstParty", new Party("FirstParty")); // all anonymously added
cave.parties.put("SecondParty", new Party("SecondParty"));
cave.parties.put("ThirdParty", new Party("ThirdParty"));

if (cave.parties.containsKey("SecondParty")) {
    cave.parties.get("SecondParty").index = ...
}

反而...

最终,这一切都取决于你想要实现的目标......

于 2013-08-27T03:07:26.373 回答
9

List.indexOf()会给你你想要的,只要你清楚地知道你在追求什么,并且equals()方法Party是明确定义的。

Party searchCandidate = new Party("FirstParty");
int index = cave.parties.indexOf(searchCandidate);

这就是有趣的地方——子类不应该检查其父类的私有属性,所以我们将equals()在超类中定义。

@Override
public boolean equals(Object o) {
    if (this == o) {
        return true;
    }
    if (!(o instanceof CaveElement)) {
        return false;
    }

    CaveElement that = (CaveElement) o;

    if (index != that.index) {
        return false;
    }
    if (name != null ? !name.equals(that.name) : that.name != null) {
        return false;
    }

    return true;
}

hashCode如果您覆盖,覆盖也是明智的equals- 任务的一般合同hashCode,如果x.equals(y),则x.hashCode() == y.hashCode()

@Override
public int hashCode() {
    int result = name != null ? name.hashCode() : 0;
    result = 31 * result + index;
    return result;
}
于 2013-08-27T02:58:53.363 回答
6

如果您想根据对象的String名称查找对象,这是 a 的教科书案例Map,比如 a HashMap。您可以使用 aLinkedHashMap并将其转换为 aListArray更高版本(Chris 在下面的评论中很好地介绍了这一点)。

LinkedHashMap因为它允许您按照插入顺序访问元素(如果您愿意)。否则HashMap还是TreeMap会做的。

您可以List按照其他人的建议使用它,但这对我来说感觉很糟糕......从短期和长期来看,这都会更干净。

如果您必须为对象使用列表,您仍然可以Map将对象名称存储到数组中的索引中。这有点难看,但你得到的性能几乎和普通的Map.

于 2013-08-27T03:03:27.723 回答
2

老实说,您可以使用list.indexOf(Object)错误,您所描述的听起来就像您最好使用Map.

尝试这个:

Map<String, Object> mapOfObjects = new HashMap<String, Object>();
mapOfObjects.put("objectName", object);

然后稍后当您要检索对象时,请使用

mapOfObjects.get("objectName");

假设您确实知道您所说的对象的名称,这将更简洁,并且具有更快的性能,特别是在地图包含大量对象的情况下。

如果您需要Map保持秩序中的对象,您可以使用

Map<String, Object> mapOfObjects = new LinkedHashMap<String, Object>();

反而

于 2013-08-27T03:06:47.280 回答
1

根据您的问题要求,我想建议 Map 将非常有效且没有任何麻烦地解决您的问题。

在 Map 中,您可以将名称作为键,将原始对象作为值。

  Map<String,Cave> myMap=new HashMap<String,Cave>();
于 2013-08-27T03:07:39.663 回答
0

我建议覆盖equals(Object)你的Party班级。它可能看起来像这样:

public boolean equals(Object o){
    if(o == null)
        return false;
    if(o instanceof String)
        return name.equalsIgnoreCase((String)o);
    else if(o instanceof Party)
        return equals(((Party)o).name);
    return false;
}

完成后,您可以使用该indexOf(Object)方法检索其名称指定的一方的索引,如下所示:

int index = cave.parties.indexOf("SecondParty");

将返回Partyname的索引SecondParty

注意:这仅适用于您正在覆盖该equals(Object)方法。

于 2013-08-27T03:05:31.960 回答
0

您可以简单地创建一个方法来通过它的名称获取对象。

public Party getPartyByName(String name) {
    for(Party party : parties) {
        if(name.equalsIgnoreCase(party.name)) {
            return party;
        }
    }
    return null;
}
于 2013-08-27T13:49:15.540 回答