11

I am seeing if there is a better/nicer way of writing a long if statement using multiple || operators.

After looking online I see a lot of examples using conditional binomial operator. Is there a way this can be used when checking if a string equals a word?

The examples online follow this structure:

int price = condition?80:100;

Here is the function:

public boolean validateLetters(String word) {
    if (word.equals("apple") || word.equals("excel") || word.equals("intern")
        || word.equals("orange") || word.equals("car")) {
      return true;
    }
    return false;
  }

The function checks to see the parameter word matches one of the following.

Is there a nicer or more efficient way I could write it?

Lii
  • 11,553
  • 8
  • 64
  • 88
william_
  • 1,131
  • 6
  • 20
  • The ternary operator generally exists to eliminate `if`, `else`, `{`, `}` and things like `return` and assignment in if-statements. You could potentially use it to eliminate `||`, `&&` or other boolean operators if you chain ternary operators, but such chaining gets really hard to read really quickly and it's almost never even actually shorter than the 2 characters you remove. Here most of the code comes not from the `||`, but from the conditions themselves, would need to exist whether you use an if-statement or the ternary operator, thus switching from one to the other won't help with those – Bernhard Barker Aug 24 '21 at 19:11
  • Does this answer your question? [Compare one String with multiple values in one expression](https://stackoverflow.com/q/10205437) – Bernhard Barker Aug 25 '21 at 04:57

4 Answers4

20

The simplest way for this specific check is to put all relevant words into a Set and use contains:

private static final Set<String> VALID_WORDS = Set.of("apple", "excel", "intern", "orange", "car");

public boolean validateLetters(String word) {
    return VALID_WORDS.contains(word);
}

Generally speaking typing out a list of very similar checks combined in some way is an indication that you should refactor your code in some way.

Oleg Cherednik
  • 17,377
  • 4
  • 21
  • 35
Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
  • is this wasting memory allocation? – william_ Aug 24 '21 at 07:56
  • 1
    the only additional info is that for this you need Java 9 – m.antkowicz Aug 24 '21 at 07:57
  • 2
    @william_: it's a one-time allocation of a small data structure. The price you pay in memory is probably much less than the additional overhead of more complicated code during development. – Joachim Sauer Aug 24 '21 at 07:59
  • 5
    @m.antkowicz: yes, but I also no longer hint if an answer requires Java 1.2. Java 9 is not a new version, and it's time to normalize *at least* that version. – Joachim Sauer Aug 24 '21 at 08:00
  • I'm not saying we should not! :) – m.antkowicz Aug 24 '21 at 08:04
  • 1
    @oleg.cherednik: thanks for the edit. Another proof that no code is short enough to not benefit from testing ;-) – Joachim Sauer Aug 24 '21 at 08:09
  • 1
    @william_ You also gain some flexibility. What if you want to add or remove a word? Or use a different set of words depending on a condition. – matt Aug 24 '21 at 08:22
  • Unless `VALID_WORDS` is used outside `validateLetters()` defining it inside `validateLetters()` would make it correctly scoped. – candied_orange Aug 24 '21 at 18:50
  • @candied_orange: not under my definition of "correctly scoped". If defined inside the method, it'll have to be re-initialized every time. – Joachim Sauer Aug 24 '21 at 19:06
  • @candied_orange It's `private`, so it's not being exposed outside. Why construct a new `Set` every time the method is called? – user Aug 24 '21 at 23:08
  • @JoachimSauer Regarding the version: Not everyone is using Java 9 yet, and it doesn't hurt to just add a line saying `Set.of` requires it. – user Aug 24 '21 at 23:13
  • 1
    @user: I know that not everyone is using it, but I strongly feel that the Java community must stop pandering to those who can never update. Java 8 is ancient by this time and those who stay there know that they can't use the latest versions. I don't think it makes sense to pepper every answer with version details when the relevant versions have been around so long. I know that's a subjective choice of mine, but it's the one I made. And Java 9 is my cut-off point. If I write code that requires 11 or 14 or 16, I'll note it. – Joachim Sauer Aug 25 '21 at 08:17
3

You can use some sort of collection as it will make code more readable:

// Use a HashSet for performance
 Set<String> values = new HashSet<String>(Arrays.asList("apple", "excel", "intern", "orange", "car"));
    
    // In your method:
  return values.contains(word);

A HashSet is used here to give good look-up performance - even very large hash sets are able to execute contains() extremely quickly.

You can also try this:

public boolean validateLetters(String word) {
    switch(word) {
        case "apple":
        case "excel":
        case "intern":
        case "orange":
        case "car":
            return true;
        default:
            return false;
    }

}
Pranav Choudhary
  • 2,726
  • 3
  • 18
  • 38
3
if (condition) {
    return true;
}
return false;

Can always be shortened to:

return condition;
Boann
  • 48,794
  • 16
  • 117
  • 146
  • 2
    This does not actually answer the question... It's correct and would be appreciated on Code Review, but it's not actually an answer to the question. – Vogel612 Aug 24 '21 at 22:55
  • @Vogel612 While the answer *is* terse, and perhaps not optimal. IMHO it does answer "Is there a nicer or more efficient way I could write it?" – Peter M Aug 26 '21 at 14:35
1

We can achieve this in regex.

public boolean validateLetters(String word) {
    if (word.matches("apple|excel|intern|orange|car")) {
      return true;
    }
    return false;
  }