首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >优化Java中历史记录的字符串数组

优化Java中历史记录的字符串数组
EN

Stack Overflow用户
提问于 2014-02-05 01:43:47
回答 1查看 1.3K关注 0票数 0

我正在寻求在优化代码方面的指导。我所写的代码是为一个基于文本的游戏编写的,在该游戏中,您可以在命令栏中键入命令。我希望在我的界面中加入的一个功能是能够滚动浏览使用向上和向下箭头键输入的最近100个命令的历史记录,以便用户更方便地玩游戏。

我设计了一个类,其中使用了一个String[],它将每个新条目存储在第二个位置(Array[1]),并将所有条目向后移动一个位置,而数组的第一个位置(Array[0])只是一个空字符串。代码将数组初始化为具有101个值,以补偿第一个位置为空行。

当用户按该顺序输入0- 100时,它应该给出与顺序相反的顺序(几乎类似于后进先出的情况,但存储最后100个值,而不是在访问后删除它们),由于0- 100是101个值,最后一个值将被覆盖。

因此,滚动历史记录会得到100,99,98,...,2,1。如果我从列表中选择50,那么它将是50,100,99,...,3,2。代码确实做到了这一点。

代码如下所示:

代码语言:javascript
复制
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;
}
}

在我的界面类中,一旦用户在命令栏中键入内容并按下enter,它将获得当前存储在命令栏中的文本,使用add方法将其添加到历史记录中,通过另一个类解析命令,然后将栏中的文本设置为空。

按向上箭头将调用向上滚动列表的下一个方法,而向下箭头将调用向下滚动列表的前一个方法。

它似乎以我希望的方式工作,但我想知道是否有某种方法来优化这段代码,或者甚至以一种完全不同的方式编写它。我制作这个游戏是为了让我自己在Java中练习,也是为了学习新的和更高级的东西,所以我很乐意听到任何关于如何做到这一点的建议。

EN

回答 1

Stack Overflow用户

发布于 2014-02-05 05:00:01

对您的问题的评论已经指出,您正试图通过实现标准Java类库在某种程度上已经提供的功能来重新发明轮子(参见LinkedList/Queue和Arraylist)。但是,既然您说希望保持在Java中练习,我想如果您尝试从头开始实现自己的命令历史记录,那就完全没问题了。

以下是我的一些观察/建议:

1)声明最终的第一个索引为1是没有必要的,也是非常违反直觉的。从默认索引0开始并在必要时添加相应的检查是很容易的。

2)忘记你的私有capacity+1()方法--它只是返回内部数组的长度(即初始大小)。相反,可以考虑添加一个公共的size()方法,该方法返回实际添加的命令数,并在添加新命令时在内部更新实际大小(参见java.util.ArrayList作为参考)。

3)此时,每次调用add(String命令)都会设置history = "",这是不必要的。如果您希望第一个索引为"",请在构造函数中设置它。这也是一个明确的迹象,表明从初始索引0开始可能会比从1开始更好。

4)一个小问题: add方法中的"if (!command.equals(""))“对于这样一个专门的类可能是可以的,但绝对应该在该方法的文档中注释它。就我个人而言,我总是让调用类来决定一个空的"“命令是否有效。此外,当使用null作为参数时,此方法将抛出未记录的NullPointerException。考虑将其更改为"if (!"".equals(command))“,或者如果添加了null,则抛出IllegalArgumentException。

5)在add方法中"if (historyi == null)“是完全不必要的,如果你在内部保留了一个指向命令的实际大小的指针--这实际上是一个特例,只有当第一个命令被添加到命令历史时(即当它的实际大小为== 0时)才会是真的。

6)在add方法实现中嵌套两个for循环也是不必要的,如果您保留指向实际大小的指针(参见下面的示例)

7)我会重新考虑是否有必要在命令历史记录中保留一个指向当前索引的指针。就我个人而言,我会避免存储这样的指针,并将这些细节留给调用类-即删除前一个和下一个方法,并提供一个向前/向后迭代器和/或对可用命令索引的随机访问。有趣的是,当从您的命令历史类中删除此功能时,它实际上归结为LinkedList或ArrayList的实现-无论您选择哪种方式。因此,最终使用一个内置的Java集合实际上是可行的。

8)最后但并非最不重要的是,我会重新考虑在列表的开头插入添加的命令是否有用-我认为将它们附加到列表的末尾会更自然,例如ArrayList。将命令添加到末尾将使得在每次调用add()期间交换所有当前命令是不必要的……

以下是对您的类的一些建议更改(未真正测试...)

代码语言:javascript
复制
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;
}

}

好吧,我想我在这方面投入了太多的时间,但我在路上学到了相当多的东西-所以谢谢;-)希望这些对你有用。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21559607

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档