2013-08-27 50 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; 
}