Cosa fare quando sono necessarie le proprietà di HashMap e ArrayList?

3

Ho una struttura dati che memorizza vari gruppi di permessi per un server di gioco multiplayer. Esiste un'istanza di una classe "Classifica" per ciascun gruppo di autorizzazioni. Ogni rango ha anche un nome. Devo essere in grado di accedere a tutti i ranghi sia in modo Iterable che con una chiave.

Ci sono tre modi principali in cui posso pensare di farlo. Non so quale sia il migliore in quanto hanno tutti pro e contro. Il primo metodo potrebbe avere un impatto significativo sulle prestazioni poiché il metodo getRank (String) verrà chiamato abbastanza spesso con un valore compreso tra 2 e 50 ranghi. Il secondo metodo potrebbe anche essere problematico in quanto vi sono diverse istanze, anche se non così comuni, in cui è utile avere un tale metodo con alte prestazioni. Il terzo metodo potrebbe essere problematico se la lista e la mappa non venissero mai sincronizzate, soprattutto perché ha bisogno di essere thread-safe.

Vorrei sapere quale metodo è il migliore e perché. La mia preoccupazione principale è che sia affidabile e performante.

Metodo # 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!");
}

Metodo n. 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
}

Metodo n. 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());
    }

}
    
posta john01dav 06.10.2015 - 05:25
fonte

1 risposta

6

Se ordini elementi per ordine di inserzione, puoi utilizzare la LinkedHashMap di Java

Non sarai in grado di visualizzarlo come un elenco, ma puoi facilmente sifonare i dati in un elenco temporaneo e restituire l'elenco. Da lì puoi ordinarlo se necessario.

Puoi anche utilizzare una SortedMap (TreeMap è la sua implementazione standard) se vuoi avere la mappa in un ordine specifico. È possibile restituire una vista elenco allo stesso modo, copiando i dati in un elenco tramite iteratore.

La dichiarazione delle variabili membro sarebbe una delle seguenti:

// Need insertion order
private 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<>();

Si restituirebbe l'elenco uno di questi modi:

// 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: so che hai detto che l'ordine non ha importanza, ma sto coprendo tutte le basi per altri lettori che potrebbero trovare utili queste informazioni.

Vedi anche:

risposta data 06.10.2015 - 05:49
fonte

Leggi altre domande sui tag