JDK-8137326 : Methods for comparing CharSequence, StringBuilder, and StringBuffer
  • Type: Enhancement
  • Component: core-libs
  • Sub-Component: java.lang
  • Affected Version: 1.4.0,5.0,6,7,8
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • Submitted: 2015-09-19
  • Updated: 2018-05-21
  • Resolved: 2018-03-01
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 11
11 b04Fixed
Related Reports
CSR :  
Relates :  
Relates :  
Relates :  
Relates :  
Relates :  
Description
FULL PRODUCT VERSION :
Linux tigger 3.13.0-63-generic #103-Ubuntu SMP Fri Aug 14 21:42:59 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux


ADDITIONAL OS VERSION INFORMATION :
Linux tigger 3.13.0-63-generic #103-Ubuntu SMP Fri Aug 14 21:42:59 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux


A DESCRIPTION OF THE PROBLEM :
Synopsis says it. Anything that implements CharSequence should be a Comparable, for example StringBuilder and StringBuffer. It's not the designer's responsibility to dictate how a class should be used. It's the designer's responsibility to provide functionality as general as possible and a CharSequence is Comparable in general.

REGRESSION.  Last worked in version 8u60

ADDITIONAL REGRESSION INFORMATION: 
True in every release.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create CharSequenceBug.java and compile using the code provided below.


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Compiling CharSequenceBug.java should compile successfully.
ACTUAL -
Compiling CharSequenceBug.java fails to compile.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Resulting compile returns:

CharSequenceBug.java:8: error: cannot find symbol
        System.err.println(sba.compareTo(sbb));
                              ^
  symbol:   method compareTo(StringBuilder)
  location: variable sba of type StringBuilder
1 error


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------

public class CharSequenceBug {

    public static void main(String[] args) {
        StringBuilder sba = new StringBuilder().append("a");
        StringBuilder sbb = new StringBuilder().append("b");
        System.err.println(sba.toString().compareTo(sbb.toString()));
        System.err.println(sba.compareTo(sbb));
    }

}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Convert to String. Severity? Simple conversion allows progress, but I need to use the StringBuilder and/or StringBuffer instead.


Comments
Another attempt to retrofit CharSequence, but to allow String to continue to implement Comparable<String>, would be to define CharSequence as follows, using the generic "self-type" idiom: interface CharSequence<T extends CharSequence<T>> extends Comparable<T> { default int compareTo(T cs) { ... } } This indeed allows String to implement Comparable<String> and correspondingly for other CharSequence implementations. However, it makes CharSequence a generic type, which means that all existing uses are turned to raw types. This is irritating because of rawtypes/unchecked warnings. But worse, existing third-party classes that implement CharSequence are now raw types, causing all generic types to be erased. This forces the class to provide compareTo(Object) even if it's already declared to be Comparable to some other type (usually itself). This is severe source incompatibility.
12-01-2018

Unfortunately, CharSequence cannot straightforwardly be retrofitted to implement the Comparable interface. Ideally one would add "implements Comparable<CharSequence>" but this causes a conflict with String, which implements Comparable<String>. One could consider modifying String to implement Comparable<CharSequence> instead. This seems most unwise. Currently, comparing two Strings using compareTo() will always return the same result, since Strings are immutable. If String is changed to allow comparisons with any CharSequence, the result of String.compareTo(cs) against the same cs object could change over time. This is likely to result in subtle and hard-to-find bugs. In addition, such a change would be incompatible with any third party subclass MyCharSeq that implements Comparable<MyCharSeq>. A better alternative would be to introduce a static method to CharSequence: static int compare(CharSequence cs1, CharSequence cs2) This would perform a comparison on a char-by-char (lexicographic) basis. A method reference of the form CharSequence::compare would be suitable as a Comparator. A case-insensitive comparison should *not* be provided. The algorithm used in String.compareToIgnoreCase() produces incorrect results in some locales. A Collator should be used instead. Changing the summary to add static method CharSequence.compare() The old summary was CharSequence Should Implement java.lang.Comparable
21-01-2016

+1 on this. StringBuffer and StringBuilder are just examples, and anyway, even if they are "just" intermediate stages to building a string, as a sequence of characters, it is still reasonable for them to be comparable, as is the case for all instances of CharSequence. Generally, there are other concrete representations of "string" (little-s) which implement CharSequence, and so it is reasonable to extend CharSequence to accommodate all read-only properties of strings.
18-01-2016

This will help performance of the new JavaDoc.
18-01-2016

This is not a bug- StringBuffer and StringBuilder are designed to be intermediate stages of building sequence of characters/string , hence not comparable. Changed Incident type to enhancement and moving to dev-team for their evaluation.
29-09-2015