2013-08-27 49 views
6

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

我只知道对象的'名字',但你不能做一个list.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; 
    } 
} 
+0

您是否需要使用列表? – smk

回答

11

由于使用的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 = ... 
} 

,而不是...

归根结底,这都将取决于你想达到什么...

+1

我相信这是最有帮助的回应。我将无法使用地图,这个难题还有一点比我在这个问题中包含的更多 – leigero

+1

@leigero如果你想要两全其美,你可以使用'HashMap'来存储'name' - > index的映射。 –

+0

即使你需要一个SSCCE由于其他原因,List的功能还是比较好,可以在后台运行这个'LinkedHashMap'并根据需要将其转换为List。地图效率更高 – StormeHawke

4

List.indexOf()会给你你想要的东西,只要你准确地知道你在做什么之后,,并规定为Partyequals()方法是明确的。

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; 
} 

如果重写equals这也是明智的覆盖hashCode - 为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; 
} 
+0

是的,你是对的,我的不好。过了漫长的一天:P –

5

如果您希望用他们String名称查找对象,这是一个经典案例的Map,说HashMap。您可以使用LinkedHashMap,稍后将其转换为ListArray(Chris在下面的评论中已经很好地说明了这一点)。

LinkedHashMap因为它允许您按照插入它们的顺序访问元素,如果您想这样做。否则HashMapTreeMap会做。

你可以像List那样与其他人建议的一起工作,但是对我来说,这感觉Hacky ......而且在短期和长期内都会更加清洁。

如果您必须使用该对象的列表,则仍然可以将对象名称的Map存储到数组中的索引。这有点丑陋,但性能几乎与普通的Map相同。

+2

特别是,你总是可以使用'map.values()。toArray(new Party [0])'转储到一个数组中,并且可以使用'new ArrayList (map.values() )'转储到列表中。 –

+1

到目前为止5或6个答案中,我最喜欢你的一个。它有O(1)查找并仍然保持插入顺序。 –

+0

@ ChrisJester-Young yup谢谢,多数民众赞成为什么我建议'LinkedHashMap',我应该明确 –

0

我建议覆盖Party类的equals(Object)。它可能是这个样子:

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"); 

将返回Party的索引名称为SecondParty

注意:这只适用于您覆盖equals(Object)方法。

+0

我也建议它违反'equals'合同,但这只是MHO:P – MadProgrammer

+0

@MadProgrammer Eh,虽然看起来很方便:P –

+1

也许很方便,但是如果你有两个'Party'对象命名为相同,但是索引是不同的。合同现在被打破;) – MadProgrammer

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>(); 

代替

1

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

在地图中,您可以将名称作为关键字,将原始对象作为值。

Map<String,Cave> myMap=new HashMap<String,Cave>(); 
0

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

public Party getPartyByName(String name) { 
    for(Party party : parties) { 
     if(name.equalsIgnoreCase(party.name)) { 
      return party; 
     } 
    } 
    return null; 
}