In this article, we are going to shed light on how to use regular expressions with the NOT operator in Java.

First, we will start with a little bit of theory on what is negation in regex. Then, we will illustrate how to implement it in Java using practical examples.

Regex NOT Operator

Simply put, regular expressions don’t provide a built-in not operator. However, we can mimic its behavior using several workarounds.

So, let’s take a close look at each option.

Using Caret ^ Anchor

Typically, the caret “^” indicates that the match must start with the specified string. For instance, the regex ^abc matches every string that begins with abc.

However, its behavior changes when it’s used inside brackets [] as it denotes the not operator.

For example, [^abc] means not containing a, b, and c. [^a-z] matches any character except lowercase letters.

Now, let’s see how to use the caret anchor to represent negation in a regex:

    
        public static void main(String[] args) {
            "I'm 34 year old".matches("[^0-9]*"); // false
            "2023 is the best year".matches("[^A-Z]*"); // true
            "DEV WITH US".matches("[^a-z]*"); // true
        }
    

Simply put, the matches() method checks a string against the specified regular expression.

Regex NOT operator using caret anchor

As we can see, “[^0-9]*“ means that the given string should not contain any digit. Alternatively, we can use [^\d] or even \D to achieve the same thing.

We used “[^A-Z]*“ regex to match a string that is not comprised entirely of uppercase letters. On the other hand, the “[^a-z]*“ pattern negates the lowercase letters.

Using Negative Lookbehind

Another solution would be using a negative lookbehind to assert that something is not preceded by particular criteria.

Basically, the syntax of the negative lookbehind is very simple: (?<!criteria)something

For example, (?<![0-9])[A-Z] asserts the negation of a digit followed by an uppercase character.

Now, let’s see how we can use a negative lookbehind as the NOT operator in regular expressions:

    
        public static void main(String[] args) {
            Pattern.compile("(?<!devv)with")
                .matcher("devwithus.com")
                .find(); // true
                
            Pattern.compile("(?<![0-9]\\s)year")
                .matcher("2023 year")
                .find(); // false
                
            Pattern.compile("(?<![a-z])[A-Z]")
                .matcher("Aa")
                .find(); // true
        }
    
  • ”(?<!devv)with” ensures that “with” is not preceded by the string “devv”

  • ”(?<![0-9]\s)year” asserts true if the specified string “year” is not preceded by a number

  • ”(?<![a-z])[A-Z]” denotes a regex that tells: NOT (a lowercase followed by an uppercase)

Using Negative Lookahead

Similarly, we can use a negative lookahead as a workaround to implement the negation operator in a regex.

In short, it ensures that something is not followed by something else. For instance, a(?!b) matches only if the character “a” is not followed by the character “b”.

So, let’s exemplify the use of negative lookahead assertions:

    
        public static void main(String[] args) {
            Pattern.compile("[0-9]+(?!\\s)")
                .matcher("2 023")
                .find(); // true
                
            Pattern.compile("@(?!gmail)")
                .matcher("email@hotmail.com")
                .find(); // true
        }
    

As shown above, “[0-9]+(?!\\s)” indicates that a digit must not be followed by a space. It returns true because there is a space after the number 2.

Secondarily, we used the ”@(?!gmail)” pattern to check that the given email is NOT a Gmail account.

Conclusion

So to summarize, we explored different ways to implement the not operator in Java regular expressions.

We have seen how to do it using the caret anchor. Then, we showcased how to achieve the same objective using negative lookbehind and lookahead.