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

2skhul33  于 2021-06-29  发布在  Java
关注(0)|答案(2)|浏览(314)

我正在尝试编写一个方法,以 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 ,例如。

tct7dpnv

tct7dpnv1#

对于您的特定用例,您有两个选项:
使用数组及其索引;
使用Map(总的来说是更好的方法)。
第一种选择:
因为在您的例子中,返回的值是从 1N (即,1,2,…,n),没有任何重复项,您只需将要比较的所有字符串转换为一个数组,遍历该数组,并使用其索引作为返回值。
首先使用以下命令创建一个数组:

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

您可以在命令字符串的声明过程中使其小写,否则以后可能会使其小写。
现在调整read命令方法:

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.asList 以及 indexOf 方法:

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);
  }

对于您的用例,第二种方法会导致更多的代码和内存使用(即,必须显式定义键),但是,其好处是:
更快,因为您可以复杂地访问密钥(即用户命令) O(1) ,而数组方法的复杂性是 O(N) 在最坏的情况下。
它使Map(命令和返回值之间)更加明确;
它对将来的代码更改更为灵活,例如,如果将来使用map方法更改代码以同时返回非连续值(或使用字符串值而不是int),则可以轻松地调整代码(即添加新命令/返回值或更改值)。
进一步改进:
在imo中,您可以通过将命令相关的关注点转移到 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 .

63lcw9qa

63lcw9qa2#

对我来说,最好的方法是:

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);

相关问题