Get specific objects from ArrayList when objects were added anonymously?

▼魔方 西西 提交于 2019-12-22 03:44:39

问题


I have created a short example of my problem. I'm creating a list of objects anonymously and adding them to an ArrayList. Once items are in the ArrayList I later come back and add more information to each object within the list. Is there a way to extract a specific object from the list if you do not know its index?

I know only the Object's 'name' but you cannot do a list.get(ObjectName) or anything. What is the recommended way to handle this? I'd rather not have to iterate through the entire list every time I want to retrieve one specific object.

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

回答1:


Given the use of List, there's no way to "lookup" a value without iterating through it...

For example...

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

Now, this will take time. If the element you are looking for is at the end of the list, you will have to iterate to the end of the list before you find a match.

It might be better to use a Map of some kind...

So, if we update Cave to look like...

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

We could do something like...

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 = ...
}

Instead...

Ultimately, this will all depend on what it is you want to achieve...




回答2:


List.indexOf() will give you what you want, provided you know precisely what you're after, and provided that the equals() method for Party is well-defined.

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

This is where it gets interesting - subclasses shouldn't be examining the private properties of their parents, so we'll define equals() in the superclass.

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

It's also wise to override hashCode if you override equals - the general contract for hashCode mandates that, if x.equals(y), then x.hashCode() == y.hashCode().

@Override
public int hashCode() {
    int result = name != null ? name.hashCode() : 0;
    result = 31 * result + index;
    return result;
}



回答3:


If you want to lookup objects based on their String name, this is a textbook case for a Map, say a HashMap. You could use a LinkedHashMap and convert it to a List or Array later (Chris has covered this nicely in the comments below).

LinkedHashMap because it lets you access the elements in the order you insert them if you want to do so. Otherwise HashMap or TreeMap will do.

You could get this to work with List as the others are suggesting, but that feels Hacky to me.. and this will be cleaner both in short and long run.

If you MUST use a list for the object, you could still store a Map of the object name to the index in the array. This is a bit uglier, but you get almost the same performance as a plain Map.




回答4:


You could use list.indexOf(Object) bug in all honesty what you're describing sounds like you'd be better off using a Map.

Try this:

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

Then later when you want to retrieve the object, use

mapOfObjects.get("objectName");

Assuming you do know the object's name as you stated, this will be both cleaner and will have faster performance besides, particularly if the map contains large numbers of objects.

If you need the objects in the Map to stay in order, you can use

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

instead




回答5:


As per your question requirement , I would like to suggest that Map will solve your problem very efficient and without any hassle.

In Map you can give the name as key and your original object as value.

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



回答6:


I would suggest overriding the equals(Object) of your Party class. It might look something like this:

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

After you do that, you could use the indexOf(Object) method to retrieve the index of the party specified by its name, as shown below:

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

Would return the index of the Party with the name SecondParty.

Note: This only works because you are overriding the equals(Object) method.




回答7:


You could simply create a method to get the object by it's name.

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


来源:https://stackoverflow.com/questions/18456192/get-specific-objects-from-arraylist-when-objects-were-added-anonymously

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!