我已经创建了一个我的问题的简短示例。我正在匿名创建对象列表并将其添加到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 :(得分:13)
鉴于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 :(得分:7)
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;
}
答案 2 :(得分:5)
如果您想根据String
名称查找对象,这是Map
的教科书案例,比如HashMap
。您可以使用LinkedHashMap
并稍后将其转换为List
或Array
(Chris已在下面的评论中详细介绍了这一点。)
LinkedHashMap
因为它允许您按照插入顺序访问元素,如果您愿意这样做的话。否则HashMap
或TreeMap
会这样做。
你可以像其他人建议的那样使用List
,但这对我来说感觉很难......而且从短期和长期来看都会更清洁。
如果必须使用对象的列表,您仍然可以将Map
对象名称存储到数组中的索引。这有点丑陋,但你得到的表现与普通Map
几乎相同。
答案 3 :(得分: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>();
代替
答案 4 :(得分:1)
根据您的问题要求,我建议Map可以非常有效地解决您的问题,而且没有任何麻烦。
在地图中,您可以将名称作为键,将原始对象作为值。
Map<String,Cave> myMap=new HashMap<String,Cave>();
答案 5 :(得分: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");
将返回名称为Party
的{{1}}的索引。
注意:这仅适用于您覆盖SecondParty
方法。
答案 6 :(得分:0)
您可以简单地创建一个方法来获取该对象的名称。
public Party getPartyByName(String name) {
for(Party party : parties) {
if(name.equalsIgnoreCase(party.name)) {
return party;
}
}
return null;
}