有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java有没有更简单的方法来编写这个equalsIgnoreCase检查链?

我正在尝试编写一个方法,该方法以string的形式接受用户输入,然后根据字符串包含/等于的内容返回int值。我已经写了一个有效的方法,但它相当长,我想知道是否有一种方法可以缩短它

这是当前状态下的方法:

private int readCommandInput(){
    System.out.print("Command?>");
    String userCommand = programAssignment.assignmentScanner.nextLine();
    if(userCommand.equalsIgnoreCase(registerNewDogCMD)){ return 1; }
    else if(userCommand.equalsIgnoreCase(listDogsCMD)){ return 2; }
    else if(userCommand.equalsIgnoreCase(increaseDogAgeCMD)){ return 3; }
    else if(userCommand.equalsIgnoreCase(removeDogCMD)){ return 4; }
    else if(userCommand.equalsIgnoreCase(registerNewOwnerCMD)){ return 5; }
    else if(userCommand.equalsIgnoreCase(giveDogCMD)){ return 6; }
    else if(userCommand.equalsIgnoreCase(listOwnersCMD)){ return 7; }
    else if(userCommand.equalsIgnoreCase(removeOwnerCMD)){ return 8; }
    else if(userCommand.equalsIgnoreCase(startAuctionCMD)){ return 9; }
    else if(userCommand.equalsIgnoreCase(makeBidCMD)){ return 10; }
    else if(userCommand.equalsIgnoreCase(listBidsCMD)){ return 11; }
    else if(userCommand.equalsIgnoreCase(listAuctionsCMD)){ return 12; }
    else if(userCommand.equalsIgnoreCase(closeAuctionsCMD)){ return 13; }
    return 0;
}

一些额外信息:

  • 前缀为CMD的变量都是程序中前面定义的strings,以及用户执行各种命令所需输入的内容。例如,makeBidCMD被定义为“投标”
  • 该方法必须能够从用户接收所有这13个不同的命令,并且如果用户输入了错误的命令,则返回0。所以总的来说,它必须能够返回14个不同的值
  • 该方法必须采用string格式的输入。例如,我不能让用户为他们想要执行的命令编写一个数字,并将输入作为int

共 (2) 个答案

  1. # 1 楼答案

    对我来说,处理这种情况的最佳方法是:

    String userCommand = programAssignment.assignmentScanner.nextLine().toLowerCase();
    
    HashMap<String, Integer> hmap = new HashMap<String, Integer>(); 
    hmap.put("aa", 1);
    hmap.put("bb", 2);
    hmap.put("cc", 3);
    hmap.put("dd", 4);
    return hmap.getOrDefault(userCommand, 0);
    
  2. # 2 楼答案

    对于您的特定用例,您有两个选项:

    1. 使用数组及其索引
    2. 使用地图(总的来说是更好的方法)

    第一个选项:

    因为,在您的例子中,返回的值是从1N即,1,2,…,N)的连续整数,没有任何重复项,所以您可以简单地将要比较的所有字符串转换为数组,在该数组上迭代,并使用其索引作为返回值

    首先使用以下命令创建一个数组:

    String[] commands = {"registerNewDogCMD", ...., "closeAuctionsCMD"}
    

    您可以在命令字符串声明期间将其大小写设置为小写,否则以后可能会使用小写

    现在调整读取命令方法:

    private int readCommandInput(String [] commands){
        System.out.print("Command?>");
        String userCommand = programAssignment.assignmentScanner.nextLine();
    
        for(int i = 0; i < vars.length; i++)
           if(userCommand.equalsIgnoreCase(vars[i]))
              return i + 1;
       return 0;
    }
    

    我们甚至可以通过使用Arrays.asListindexOf方法使其更简单:

       private static int readCommandInput(String[] commands){
           ...
           return Arrays.stream(commands).map(String::toLowerCase)
                                         .collect(Collectors.toList())
                                         .indexOf(userCommand) + 1;
      }
    

    第二个选项:

    此选项(即使用Map是最合适的,并且最适合于返回的值不是连续整数或可能有重复值的用例。如下所示(使用Java 9):

    Map<String, Integer> commands = Map.of(entry("registernewdogcmd", 1),...,  entry("closeauctionscmd", 13));
    

    用户案例:

     private static int readCommandInput(Map<String, Integer> commands, int default_value){
           System.out.print("Command?>");
           String userCommand = programAssignment.assignmentScanner.nextLine().toLowerCase();
           return commands.getOrDefault(userCommand, default_value);
      }
    

    对于您的用例,第二种方法会导致更多的代码和内存使用(即,必须显式定义键),但是,其好处是:

    1. 更快,因为您可以以O(1)的复杂度访问密钥(即,用户命令),而使用数组方法,在最坏的情况下,您的复杂度为O(N)
    2. 它使映射(命令和返回值之间)更加明确
    3. 它对将来的代码更改更为灵活,例如,如果将来您使用map方法更改代码以同时返回非连续值(或使用字符串值而不是int),您可以轻松地调整代码(,即,添加新命令/返回值或更改值)

    进一步改进:

    在我看来,您可以通过将与命令相关的关注点移动到Enum中来进一步改进代码,这将增加可读性和关注点的分离。设计如下所示:

    public enum Commands {
        REGISTER_NEW_DOG_CMD(1, "registerNewDogCMD"),
        ....
        CLOSE_AUCTION_CMD(13, "closeAuctionsCMD");
    
        private static final int COMMAND_DOES_NOT_EXIST = 0;
        private static final Map<String, Integer> LOOK_UP = new HashMap<>(Commands.values().length);
    
        static{
            Arrays.stream(Commands.values())
                  .forEach(c -> LOOK_UP.put(c.getName().toLowerCase(), c.getValue()));
        }
    
        private final int value;
        private final String name;
    
        Commands(int value, String name) {
            this.value = value;
            this.name = name;
        }
    
        public int getValue() {
            return value;
        }
    
        public static int getValue(String userCommand) {
            return LOOK_UP.getOrDefault(userCommand.toLowerCase(), COMMAND_DOES_NOT_EXIST);
        }
    
        public String getName() {
            return name;
        }
    }
    

    然后将方法更改为:

       private int readCommandInput(){
            System.out.print("Command?>");
            String userCommand = programAssignment.assignmentScanner.nextLine();
            return Commands.getValue(userCommand);
        }
    

    理想情况下,您可以更改签名以返回Enum命令类型,而不是int