I have the following List of objects:
private List<Object> teamlist = new ArrayList<Object>();
And I'm adding objects to the list like so:
teamlist.add(new MCWarTeam(args[0], joinkey));
Now the objects in the list have no name, but can be referenced by using the list, right? Before I add a new element to the list, how can I check if an object with a certain attribute already exists? This is the constructor of the Objects:
public MCWarTeam(String teamname, String joinkey){
this.teamname = teamname;
this.joinkey = joinkey;
}
I want to check if there already is a team with the name teamname. Alternatively, is there a better way to store the Objects? Before, I just used a HashMap to add the teamname and joinkey and it worked just fine, but figured using Objects instead would be a better way to do it.
Here is the important code for the event handler:
else if (cmd.getName().equalsIgnoreCase("createTeam")) {
if (args.length > 0 && args.length < 3) {
String joinkey = "";
if (args.length > 1)
joinkey = args[1];
String teamname = args[0];
MCWarTeam newTeam = new MCWarTeam(teamname, joinkey);
if (!teamlist.containsKey(teamname)) {
teamlist.put(teamname, newTeam);
sender.sendMessage("Created new team \"" + teamname + "\" with join key \"" + joinkey + "\" successfully! Teams:");
sender.sendMessage("All teams:");
for (String key : teamlist.keySet()) {
sender.sendMessage(key);
}
} else
sender.sendMessage("Team already exists!");
return true;
}
return false;
}
else if (cmd.getName().equalsIgnoreCase("joinTeam")) {
if (args.length > 0 && args.length < 3) {
String joinkey = "";
if (args.length > 1)
joinkey = args[1];
String teamname = args[0];
if (teamlist.containsKey(teamname)) {
String teamKey = teamlist.get(teamname).getJoinKey();
if (joinkey == teamKey) {
teamlist.get(teamname).addPlayer(playername);
Bukkit.broadcastMessage("MCWar: " + playername + " joined Team \"" + teamname + "\" successfully!");
} else
sender.sendMessage("Join key incorrect!");
} else {
sender.sendMessage("Team doesn't exist! Teams:");
for (String key : teamlist.keySet()) {
sender.sendMessage(key);
}
}
return true;
}
return false;
}
Basically, if it returns false, the user will get a message explaining the correct usage of the command he entered.
Java's List<T>
has a boolean contains(Object)
method, which is handy for situations when you wish to avoid duplicates:
if (!teamlist.contains(newTeam)) {
teamlist.add(newTeam);
}
MCWarTeam
class must implement equals
in order for this to work. When you override equals
, you must also override hashCode
.
@Override
public boolean equals(Object obj) {
if (!(obj instanceof MCWarTeam)) {
return false;
}
MCWarTeam other = (MCWarTeam)obj;
return teamname.equals(other.teamname)
&& joinkey.equals(other.joinkey);
}
@Override
public int hashCode() {
return 31*teamname.hashCode()+joinkey.hashCode();
}
I'm just looking to check if an
Object
with the sameteamname
already exists, but not care about thejoinkey
?
If joinkey
is not part of your object's state that influences equality, it is usually not a good idea to keep it as part of the object as a field. For example, if joinkey
is something transient which you use to "connect" teams to other things, making a HashMap<String,MCWarTeam>
, using joinkey
as the key to the map, and removing joinkey
from MCWarTeam
should be a good idea.
Based on the description and your comments to other answers, it seems like a good idea to not use a List
, but instead store your data in a Map<String, MCWarTeam>
, which maps team names into MCWarTeam
objects:
private Map<String, MCWarTeam> teams = new HashMap<>();
You can add a team, checking whether a team with the same name already exists, like this:
String teamName = args[0];
if (!teams.containsKey(teamName)) {
teams.put(teamName, new MCWarTeam(teamName, joinKey));
} else {
// do what you want when the team name was already in the map
}
Retrieving an MCWarTeam
object based on team name, e.g. for accessing the joinKey
attribute, is easy:
String joinKey = teams.get(teamName).getJoinKey();
Note that using this approach, you shouldn't implement equals
or hashCode
in MCWarTeam
, because you aren't gonna need it; as your map keys are team names, containsKey
operates on String
objects which already have well-defined equals
and hashCode
semantics.
In order to search for an MCWarTeam
instance in the ArrayList, you'll first have to override equals
in order to define what it means for two MCWarTeam
instances to be equal to each other. Then you can use indexOf(team)
or contains
to determine whether a instance is in the List
.
However, such a search would take linear time, so a HashSet
may be better for your needs (for that purpose you'll need to override both equals
and hashCode
, and you'll be able to find if an object is in the Set
in constant time).
If you implement MCWarTeam
equals
method properly, then contains
should tell you if the object exists.
boolean exists = teamlist.contains(member);
And as @Eran mentioned a HashSet
would give you O(1)
lookup where list contains
is O(n)
, the only thing is that HashSet
doesn't allow duplicates.
And Yes, use the actual type rather than Object
List<MCWarTeam> teamlist = new ArrayList<>();
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With