I have a data structure that stores various permission groups for a multiplayer game server. There is an instance of a "Rank" class for each permission group. Each rank also has a name. I need to be able to access all of the ranks both in a Iterable fashion and with a key.
There are three main ways I can think of doing this. I don't know which one is best as they all have pros and cons. The first method could have a significant performance impact as the getRank(String) method will be called quite often with anywhere from about 2-50 ranks. The second method could also be problematic as there are several instances, although not nearly as common, where it is useful to have such a method with high performance. The third method could be problematic if the list and map ever get out of sync, especially since it needs to be thread-safe.
I would like to know which method is best and why. My primary concern is that it is both reliable and performant.
Method #1
public synchronized Rank getRank(String name) throws IllegalArgumentException{
for(Rank rank : ranks){
if(rank.getName().equalsIgnoreCase(name)){
return rank;
}
}
throw new IllegalArgumentException("Rank: " + name + " does not exist!");
}
Method #2:
public synchronized List<Ranks> getRanks(){
ArrayList<Ranks> ranksList = new ArrayList<Ranks();
for(String rankName : ranksMap.keySet()){
ranksList.add(ranksMap.get(rankName));
}
return Collections.unmodifiableList(ranksList); //unmodifiableList to prevent someone from trying to add or remove ranks by editing this list
}
Method #3:
public class RankList{
private ArrayList<Rank> list = new ArrayList<>();
private Map<String, Rank> map = new HashMap<>();
public void add(Rank rank){
list.add(rank);
map.put(rank.getName().toLowerCase(), rank);
}
public List<Rank> getRanks(){
return Collections.unmodifiableList(list);
}
public Rank get(String name){
return map.get(name.toLowerCase());
}
}