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 #1public 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());    }}
What to do when properties of a HashMap and ArrrayList are neccessary?
java;performance;data structures;collections
If you order elements by insertion order, you can use Java's LinkedHashMapYou will not be able to view it as a list, but you can easily siphon data into a temporary list and return that list. From there you can sort it if necessary.You can also use a SortedMap (TreeMap is its standard implementation) if you want to have the map in a specific order. You can return a list view the same way, copying data into a list via iterator.Member variable declaration would be one of the following:// Need insertion orderprivate Map<String, Rank> map = new LinkedHashMap<>();// Need key order or some other order (can pass in comparator)private Map<String, Rank> map = new TreeMap<>();// Do not care about order.private Map<String, Rank> map = new HashMap<>();You would return the list one of these ways:// Using map order or do not care about order.public List<Rank> getRanks() {  return new ArrayList<Rank>(map.values());}// Using some other order.public List<Rank> getRanks() {  List<Rank> values = new ArrayList<Rank>(map.values());  Collections.sort(values); // can pass in comparator  return values;}NB: I know you said order does not matter, but I am covering all the bases for other readers who might find this information useful.See also:Ordered List Map implementation in JavaHow to convert a Map to List in Java?