Optimisation du code un tableau de chaînes pour un historique en Java


Je cherche des conseils dans le respect de l'optimisation du code. Le code que j'ai écrit est pour un jeu basé sur du texte dans lequel vous tapez des commandes dans une barre de commandes. Une fonctionnalité que je souhaitais intégrer dans mon interface était la possibilité de faire défiler l'historique des 100 dernières commandes saisies à l'aide des touches fléchées haut et bas afin qu'il soit plus pratique pour l'utilisateur de jouer au jeu.

J'ai conçu une classe dans laquelle utilise un {[1] } qui stockera chaque nouvelle entrée dans le deuxième position (Array[1]) et déplacez toutes les entrées d'une position tandis que la première position du tableau (Array[0]) est juste une chaîne vide et vide. Le code initialise le tableau pour avoir 101 valeurs pour compenser la première position étant une ligne vide.

Lorsqu'un utilisateur entre 0 à 100 dans cet ordre, il devrait alors me donner l'inverse de l'ordre (presque comme une situation de dernière entrée, première sortie, mais stockant les 100 dernières valeurs plutôt que de les supprimer une fois accessibles), et depuis 0 - 100 101 valeurs, la dernière valeur sera écrasée.

Ainsi, en faisant défiler l'histoire, cela me donnerait 100, 99, 98,..., 2, 1. Si je devais sélectionner 50 dans la liste, ce serait alors 50, 100, 99, ..., 3, 2. Le code fait en effet cela.

Le code est listé ci-dessous:

public class CommandHistory {
private String[] history;
private final int firstIndex = 1;
private static int currentIndex = 0;

/**
 * Default constructor, stores last 100 entries of commands plus the blank
 * entry at the first index
 */
public CommandHistory() {
    history = new String[101];
}

/**
 * Constructor with a capacity, stores the last (capacity) entries of
 * commands plus the blank entry at the first index
 * 
 * @param capacity
 *            Capacity of the commands history list
 */
public CommandHistory(int capacity) {
    history = new String[capacity + 1];
}

/**
 * Returns the size (length) of the history list
 * 
 * @return The size (length) of the history list
 */
private int size() {
    return history.length;
}

/**
 * Adds a command to the command history log
 * 
 * @param command
 *            Command to be added to the history log
 */
public void add(String command) {
    history[0] = "";
    if (!command.equals("")) {
        for (int i = firstIndex; i < size();) {
            if (history[i] == null) {
                history[i] = command;
                break;
            } else {
                for (int j = size() - 1; j > firstIndex; j--) {
                    history[j] = history[j - 1];
                }
                history[firstIndex] = command;
                break;
            }
        }
        currentIndex = 0;
    }
}

/**
 * Gets the previous command in the history list
 * 
 * @return The previous command from the history list
 */
public String previous() {
    if (currentIndex > 0) {
        currentIndex--;
    }
    return history[currentIndex];
}

/**
 * Gets the next command in the history list
 * 
 * @return The next command from the history list
 */
public String next() {
    if (currentIndex >= 0 && (history[currentIndex + 1] != null)) {
        currentIndex++;
    }
    return history[currentIndex];
}

/**
 * Clears the command history list
 */
public void clear() {
    for (int i = firstIndex; i < size(); i++) {
        history[i] = null;
    }
    currentIndex = 0;
}

/**
 * Returns the entire command history log
 */
public String toString() {
    String history = "";
    for (int i = 0; i < size(); i++) {
        history += this.history[i];
    }
    return history;
}
}

Dans ma classe interface, une fois que l'utilisateur tape quelque chose dans la barre de commandes et frappe entrée, il obtiendra le texte actuellement stocké dans la barre, utilise la méthode add pour l'ajouter à l'historique, analyse la commande via une autre classe, puis définit le texte dans la barre à vide.

Appuyer sur la flèche vers le haut appelle la méthode suivante qui fait défiler la liste, et la flèche vers le bas appelle la méthode précédente qui fait défiler la liste.

Il semble fonctionner de toutes les manières que je le souhaite, mais je me demandais s'il y avait un moyen d'optimiser ce code ou peut-être même de le coder d'une manière complètement différente. Je fais ce jeu pour me maintenir pratiqué en Java et aussi pour apprendre de nouvelles et plus encore des choses avancées, donc j'aimerais entendre des suggestions sur la façon de le faire.

Author: Makoto, 2014-02-04

1 answers

Les commentaires à votre question ont déjà souligné que vous essayez en quelque sorte de réinventer la roue en implémentant les fonctionnalités que la bibliothèque de classes Java standard fournit déjà dans une certaine mesure (voir LinkedList/Queue et Arraylist). Mais puisque vous dites que vous voulez vous maintenir pratiqué en Java, je suppose que c'est parfaitement bien si vous essayez d'implémenter votre propre historique de commandes à partir de zéro.

Voici quelques-unes de mes observations/suggestions:

1) Il n'est pas nécessaire et très contre-intuitif pour déclarer un premier indice final de 1. Il serait facile de commencer avec un index par défaut de 0 et d'ajouter les vérifications correspondantes si nécessaire.

2) Oubliez votre méthode private size () - elle renvoie simplement la longueur du tableau interne de toute façon (c'est-à-dire la capacité initiale+1). Envisagez plutôt d'ajouter une méthode public size () qui renvoie le nombre réel de commandes ajoutées et met à jour en interne la taille réelle lors de l'ajout de nouvelles commandes (voir par exemple java.util.Liste de tableaux pour référence).

3) Pour le moment, chaque appel à add(commande String) définira history[0]="", ce qui n'est pas nécessaire. Si vous souhaitez que le premier indice "", défini dans le constructeur. C'est aussi un signe clair, qu'il serait peut-être préférable de commencer avec un premier indice de 0 au lieu de 1.

4) Un problème mineur: "si (!commande.equals ( "")) " pendant votre méthode add est peut-être OK pour une telle classe spécialisée, mais il devrait certainement être commenté dans la documentation de la méthode. Personnellement, je laisserais toujours la classe appelante décider si une commande "" vide est considérée comme valide ou non. De plus, cette méthode lancera une NullPointerException non documentée, lorsque null est utilisé comme argument. Envisagez de changer cela en " if (!"".equals(command))" ou lancer une exception IllegalArgumentException si null est ajouté.

5) "if (history [i] = = null)" pendant la méthode add est complètement inutile, si vous gardez en interne un pointeur sur la taille réelle des commandes-c'est en fait un cas particulier qui ne sera vrai que lorsque la toute première commande est ajoutée à l'historique des commandes (c'est-à-dire quand sa taille réelle == 0).

6) Avoir deux boucles for imbriquées dans votre implémentation de méthode add est également inutile, si vous gardez un pointeur sur la taille réelle (voir l'exemple ci-dessous)

7) Je reconsidérerais s'il est nécessaire de garder un pointeur sur l'index actuel dans l'historique des commandes. Personnellement j'éviterais de stocker un tel pointeur et laisserais ces détails à la classe appelante - c'est-à-dire supprimer les méthodes précédentes et suivantes et fournir un itérateur avant/arrière et/ou un accès aléatoire à l'index des commandes disponibles. Fait intéressant, lorsque cette fonctionnalité est supprimée de votre classe d'historique de commandes, elle se résume en fait à une implémentation d'une LinkedList ou d'une ArrayList - quelle que soit la façon dont vous allez. Donc, à la fin, l'utilisation de l'une des collections Java intégrées serait en fait la voie à suivre.

8) Enfin et surtout je reconsidérerais si c'est le cas utile pour insérer des commandes ajoutées au début de la liste - je crois qu'il serait plus naturel de les ajouter à la fin comme le fait ArrayList. L'ajout des commandes à la fin rendrait inutile l'échange de toutes les commandes en cours lors de chaque appel à add ()...

Voici quelques-unes des modifications suggérées à votre classe (pas vraiment testées...)

public class CommandHistory {
private String[] history;
private int size;
private static int currentIndex = 0;

/**
 * Default constructor, stores last 100 entries of commands plus the blank
 * entry at the first index
 */
public CommandHistory() {
    this(100);
}

/**
 * Constructor with a capacity, stores the last (capacity) entries of
 * commands plus the blank entry at the first index
 * 
 * @param capacity
 *            Capacity of the commands history list
 */
public CommandHistory(int capacity) {
    history = new String[capacity];
}

/**
 * Returns the size (length) of the history list
 * 
 * @return The size (length) of the history list
 */
public int size() {
    return size;
}

/**
 * Adds a command to the command history log
 * 
 * @param command
 *            Command to be added to the history log
 */
public void add(String command) {
    if (!"".equals(command)) {
        if (this.size < history.length) {
            this.size++;
        }
        for (int i = size-1; i >0; i--) {
            history[i] = history[i-1];
        }
        history[0] = command;
        currentIndex = 0;
    }
}

/**
 * Gets the previous command in the history list
 * 
 * @return The previous command from the history list
 */
public String previous() {
    if (currentIndex >= 0 && currentIndex < size-1) {
        currentIndex++;
    }
    return history[currentIndex];
}

/**
 * Gets the next command in the history list
 * 
 * @return The next command from the history list
 */
public String next() {
    if (currentIndex > 0 && currentIndex < size) {
        currentIndex--;
    }
    return history[currentIndex];
}

/**
 * Clears the command history list
 */
public void clear() {
    for (int i = 0; i < size; i++) {
        history[i] = null;
    }
    currentIndex = 0;
}

/**
 * Returns the entire command history log
 */
public String toString() {
    String history = "";
    for (int i = 0; i < size; i++) {
        history += this.history[i] + ", ";
    }
    return history;
}

}

Eh Bien, je suppose que j'ai investi beaucoup trop de temps pour cela, mais j'ai appris pas mal moi-même à la manière grâce ;-) J'espère que certains de cela est utile pour vous.

 2
Author: Balder, 2014-02-04 21:06:13