简体   繁体   中英

what is the better alternative to following if-else ladder in java?

Situation : I am examining filenames , the filename is stored in a String variable called str and according to the conditions checked in if statements i am setting the value of a variable called mailType .

if(str.contains("template"))
        {                   
          if(str.contains("unsupported"))
              mailType="unsupported";      
              else
                  if(str.contains("final_result"))                
                      mailType="final_result";            
                  else
                      if(str.contains("process_success"))
                          mailType="Process Success"; 
                      else
                          if(str.contains("receive"))                         
                              mailType="Receive";                         
                          else
                          if(str.contains("sen"))
                              mailType="sent"; 
                          else
                              if(str.contains("welcome"))
                                  mailType="welcome";
                              else
                                  if(str.contains("manual"))
                                     mailType="Manual";                    
        }       
        else                
if(str.contains("properties"))
        {

          if(str.contains("unsupported"))
              mailType="unsupported";      
              else
                  if(str.contains("final_result"))                
                      mailType="final_result";            
                  else
                      if(str.contains("process_success"))
                          mailType="Process Success"; 
                      else
                          if(str.contains("receive"))                         
                              mailType="Receive";                         
                          else
                          if(str.contains("sen"))
                              mailType="sent"; 
                          else
                              if(str.contains("welcome"))
                                  mailType="welcome";
                              else
                                  if(str.contains("manual"))
                                     mailType="Manual";

        }

Problem : Is there any better way to do this in java that shortens my code and is memory friendly ?

Use a LinkedHashMap<String, String> :

LinkedHashMap<String, String> mapping = new LinkedHashMap<>();
mapping.put("unsupported", "unsupported");
mapping.put("final_result", "final_result");
// ... etc

Then iterate the map until you find a matching key:

for (Map.Entry<String, String> entry : mapping.entrySet()) {
  if (str.contains(entry.getKey()) {
    mailType = entry.getValue();
    break;
  }
}

The key point here is that LinkedHashMap preserves insertion order (unlike HashMap ) so you can actually specify the order in which you want to test for matches (other map implementations do this too, eg Guava's ImmutableMap ; LinkedHashMap is simply one that you have out of the box).

If you need to nest this for the outer cases, you can simply apply the same pattern:

LinkedHashMap<String, LinkedHashMap<String, String>> outerMapping =
    new LinkedHashMap<>();
outerMapping.put("template", mapping);
outerMapping.put("properties", someOtherMapping);

And then just iterate through the keys in the same way:

for (Map.Entry<String, LinkedHashMap<String, String>> outerEntry : outerMapping.entrySet()) {
  if (str.contains(outerEntry.getKey()) {
    // Apply the iteration above, using outerEntry.getValue().
  }
}

You've said you find Andy's answer (which is what I'd do) too complex. His original comment suggesting else if may be an option for you:

if (str.contains("template")) {
    if (str.contains("unsupported"))
        mailType = "unsupported";
    else if (str.contains("final_result"))
        mailType = "final_result";
    else if (str.contains("process_success"))
        mailType = "Process Success";
    else if (str.contains("receive"))
        mailType = "Receive";
    else if (str.contains("sen"))
        mailType = "sent";
    else if (str.contains("welcome"))
        mailType = "welcome";
    else if (str.contains("manual"))
        mailType = "Manual";
} else if (str.contains("properties")) {
    if (str.contains("unsupported"))
        mailType = "unsupported";
    else if (str.contains("final_result"))
        mailType = "final_result";
    else if (str.contains("process_success"))
        mailType = "Process Success";
    else if (str.contains("receive"))
        mailType = "Receive";
    else if (str.contains("sen"))
        mailType = "sent";
    else if (str.contains("welcome"))
        mailType = "welcome";
    else if (str.contains("manual"))
        mailType = "Manual";
}

or better yet, with consistent use of {}:

if (str.contains("template")) {
    if (str.contains("unsupported")) {
        mailType = "unsupported";
    } else if (str.contains("final_result")) {
        mailType = "final_result";
    } else if (str.contains("process_success")) {
        mailType = "Process Success";
    } else if (str.contains("receive")) {
        mailType = "Receive";
    } else if (str.contains("sen")) {
        mailType = "sent";
    } else if (str.contains("welcome")) {
        mailType = "welcome";
    } else if (str.contains("manual")) {
        mailType = "Manual";
    }
} else if (str.contains("properties")) {
    if (str.contains("unsupported")) {
        mailType = "unsupported";
    } else if (str.contains("final_result")) { 
        mailType = "final_result";
    } else if (str.contains("process_success")) {
        mailType = "Process Success";
    } else if (str.contains("receive")) {
        mailType = "Receive";
    } else if (str.contains("sen")) {
        mailType = "sent";
    } else if (str.contains("welcome")) {
        mailType = "welcome";
    } else if (str.contains("manual")) { 
        mailType = "Manual";
    }
}

Try this

static String containsAndValue(Collection<String> collection, String oldValue, String... strings) {
    if (strings.length % 2 != 0)
        throw new IllegalArgumentException("strings");
    for (int i = 0; i < strings.length; i += 2)
        if (collection.contains(strings[i]))
            return strings[i + 1];
    return oldValue;
}

and

if (str.contains("template")) {
    mailType = containsAndValue(str, mailType,
        "unsupported", "unsupported",
        "final_result", "final_result",
        "process_success", "Process Success",
        "receive", "Receive",
        "sen", "sent",
        "welcome", "welcome",
        "manual", "Manual");
} else if (str.contains("properties")) {
    mailType = containsAndValue(str, mailType,
        "unsupported", "unsupported",
        "final_result", "final_result",
        "process_success", "Process Success",
        "receive", "Receive",
        "sen", "sent",
        "welcome", "welcome",
        "manual", "Manual");
}

Is this less complex?

public enum MailType {
    UNSUPPORTED("unsupported", "unsupported"),
    FINAL_RESULT("final_result", "final_result"),
    PROCESS_SUCCESS("process_success", "Process Success"),
    RECEIVE("receive", "Receive"),
    SENT("sen", "sent"),
    WELCOME("welcome", "welcome"),
    MANUAL("manual", "Manual");

    private final String query;
    private final String value;

    MailType(String query, String value) {
        this.query = query;
        this.value = value;
    }

    public static String find(String text){
        for(MailType mailType: values()){
            if(text.contains(mailType.query)) {
                return mailType.value;
            }
        }
        return null;
    }
}

And use it like this:

String mailType = MailType.find(str);

First, if you use else if instead of simple else , you will have less indentation.

if(str.contains("unsupported"))
          mailType="unsupported";      
else if(str.contains("final_result"))                
          mailType="final_result";            
else if(str.contains("process_success"))
          mailType="Process Success"; 
else if(str.contains("receive"))                         
          mailType="Receive";                         
else if(str.contains("sen"))
          mailType="sent"; 
else if(str.contains("welcome"))
          mailType="welcome";
else if(str.contains("manual"))
          mailType="Manual";        

In your particular case, i would suggest to try to use regular expression to simplify a bit your work :

Pattern p = Pattern.compile("(unsupported|final_result|welcome)");
Matcher m = p.matcher(str);
if (m.matches()) {
    mailType = m.group(1);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM