1
votes

I have a CharSequence object and a String object. I want to compare both for equality check(case insensitivity) with possible null values. I used nested if statements which is not so clean and optimised. Problem is I cannot call toString() on a null CharSequence object. How can I achieve equality check ?

4
What if both are null? Should they be considered as equal? - Daniele Pantaleone
Yes @DanielePantaleone - sagar suri

4 Answers

3
votes

There will be no much complicated code and no nested if's. Below should do.

if(Objects.equals(charSeq,str) || (charSeq !=null && str !=null && charSeq.toString().equalsIgnoreCase(str))) {
   // todo
}
2
votes

As far as I understand your question, it is this: You have two objects, and you want to see if they're equal.

What we'd WANT to do is to use String.equalsIgnoreCase(). It's literally precisely what you want. If the CharSequence object is not null, it's pretty easy, because CharSequence.toString() returns a string with the exact same characters in the exact same order.

charSequence.toString().equalsIgnoreCase(otherString);

Unfortunately this doesn't work. If the charsequence is null, then this throws a NullPointerException. So we need to see if the charsequence is null, and proceed from there.

public boolean compareCSAndString(CharSequence cs, String string) {
  if(cs == null) {
    // If both are null, then they're equal
    return string == null; 
  }
  else {
    return cs.toString().equalsIgnoreCase(string);
  }
}

This ticks all the boxes:

  • It's case insensitive
  • It handles null values
  • It is clean and easy to read (no nested ifs)
0
votes
if (charSeq == str ||  (charSeq != null && str != null && charSeq.toString().equalsIgnoreCase(str))) {
   // todo
}

charSeq == str handle the case when both are null (only this case since they belong to different classes and cannot then identify the same object reference

0
votes

Using directly equals() will not work as equals() of CharSequence subclasses are not interoperable between.
You could use the toString() method as a bridge between the CharSequence subclasses as it is interoperable in some cases (String and StringBuilder for example) but it is not in all cases.

For example invoking toString() on a CharBuffer object may give a specific result as CharBuffer.toString() relies on the buffer current position .

To have consistent results, I think that you have not other choice that first checking the type of the object passed and then perform the comparison consequently : using toString() as bridge for StringBuilder/StringBuffer and handle differently other types.

For the bridge comparison, supposing that you expect only StringBuilder or String as subclasses:

public boolean compareContent(CharSequence charSequence, String string) {
  if (!(charSequence instanceof StringBuilder || charSequence instanceof String){
      // Exception, logging, more customized comparison or return false
  }
  return charSequence.toString().equalsIgnoreCase(string));
}