Win a copy of Re-engineering Legacy Software this week in the Refactoring forum
or Docker in Action in the Cloud/Virtualization forum!
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

string comparison with compareTo() method

 
Timo Richter
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi there,

maybe my question seems to be a bit hairsplitting:
If I want to compare two Strings lexicographically, I use the compareTo() Method of the String class:

public int compareTo(String anotherString)

The API specification says this about the return value:

Returns:
the value 0 if the argument string is equal to this string; a value less than 0 if this string is lexicographically less than the string argument; and a value greater than 0 if this string is lexicographically greater than the string argument.

After having read this, I wasn't sure if it could return e.g. 5 or -4 in certain cases. So I divided the return value by the absolute value of itself to be sure that I get either 1 or -1 and got nitpicked with it.

My question now is, if and why I can assume the method only returns 0, 1 or -1.

A test supports this assumption:
"AAA".compareTo( "AAA" ) returns 0
"AAA".compareTo( "BBB" ) returns -1
"BBB".compareTo( "AAA" ) returns 1

Thanks
Timo
[ October 10, 2007: Message edited by: Timo Richter ]
 
fred rosenberger
lowercase baba
Bartender
Posts: 12086
29
Chrome Java Linux
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
does it matter if it returns -5 instead of -1?
 
Timo Richter
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, my method (in which I use the compareTo()-statement) has to return either 0, 1 or -1. So if it's possible that compareTo() returns something else (like 5 or -4) I have to change it into 0, 1, -1 - what I did in my solution for the assignment.
But actually it seems to me, compareTo() returns only 0, 1, -1 even if the API spec does not explicitly mention it...So I could omit the transfomation which would reduce the amount of code. But, how can I be sure?
[ October 11, 2007: Message edited by: Timo Richter ]
 
Katrina Owen
Sheriff
Posts: 1367
18
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
How about saving a value that you assume would be either 4 or -5 or some such thing in a variable, and then test it for equality for all the numbers between -10 and 10?
 
Mladen Grabowsky
Greenhorn
Posts: 29
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi timo,

But actually it seems to me, compareTo() returns only 0, 1, -1 even if the API spec does not explicitly mention it...So I could omit the transfomation which would reduce the amount of code. But, how can I be sure?

It seems to me too

But if you really want to make sure, why not test if the returned value is:
- equal to 0
- lower than 0
- higer than zero

btw., i have never tested for that, to me, it is suficient when i treat all return values as either -1, 0 or 1
 
Marilyn de Queiroz
Sheriff
Posts: 9059
12
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I think you could easily write a test to see if '1' or '-1' is always returned. However, since the API is not specific, as you and Mladen point out, I think it would be better to use the constraints that the API (and Mladen) suggest. I recommend testing for the relationship to zero rather than a specific number. Then, as Fred notes, it really wouldn't matter if the return value is -1 or -5 since both are less than zero.
 
Jim Yingst
Wanderer
Sheriff
Posts: 18671
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
[MdQ]: I think you could easily write a test to see if '1' or '-1' is always returned.

True - however such a test may give misleading results. It's very common to see compareTo() methods which return only -1, 0, or 1, and therefore it's quite possible that a test will show that the method "always" returns those values. But that just means that the tester hasn't tried enough different Comparable classes. (Hint: try comparing two String values.)
 
Mladen Grabowsky
Greenhorn
Posts: 29
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Jim Yingst:
[MdQ]: I think you could easily write a test to see if '1' or '-1' is always returned.

True - however such a test may give misleading results. It's very common to see compareTo() methods which return only -1, 0, or 1, and therefore it's quite possible that a test will show that the method "always" returns those values. But that just means that the tester hasn't tried enough different Comparable classes. (Hint: try comparing two String values.)

Thanks for the hint Jim, it's much appreciated.

You're right, the string implementation may (and certinly will) return more values than just 1, 0 an -1.

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html#compareTo(java.lang.String)


....
If there is no index position at which they differ, then the shorter string lexicographically precedes the longer string. In this case, compareTo returns the difference of the lengths of the strings -- that is, the value:

this.length()-anotherString.length()


So, one should always just check, if the returned value is equal to zero, higer than zero or lower than zero.
 
Timo Richter
Greenhorn
Posts: 10
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanks a lot for your interest and support.

In the meantime I wrote a test which leads to the same results as Mladen found in the 1.5.0 API docs (as we use 1.4 for the assignments I had only looked at the 1.4.2 API docs before):

My first test compared two (poorly chosen) Strings of the same length and misled to the conclusion compareTo() always returns either 0, 1 or -1, even if not explicitely mentioned in the API:

"AAA".compareTo( "AAA" ) = 0
"AAA".compareTo( "BBB" ) = -1
"BBB".compareTo( "AAA" ) = 1

A second test comparing randomly generated Strings of random length from 1 to 10 demonstrates that compareTo() also returns values other than 0, 1 or -1:

(pseudocode)
"A^3k".compareTo( "snOSyqJmbg" ) = -50
"FD1(&H".compareTo( "dT_B" ) = -30
"bNS".compareTo( "HuPF@7*09" ) = 26
"7&|S>5A=".compareTo( "uA;1" ) = -62
"+v".compareTo( "dMl67s*=-O" ) = -57
"ng#".compareTo( "1z)B"ZRenw" ) = 61

[Marilyn de Queiroz]:
I recommend testing for the relationship to zero rather than a specific number.

[Mladen Grabowsky]:
So, one should always just check, if the returned value is equal to zero, higer than zero or lower than zero.


The first approach (dividing the result by its absolute value (if not zero) to get either 1 or -1) seems not to be completely false to me. After all it transforms a positive result to 1 and a negative to -1 no matter what compareTo() actually returned.
But clearly, as you stated, the comparison against zero (equal, lower or higher) is the best choice (simpler, faster and more readable).
So this is what I'll use for the assignment.

Once again thank you all for your fast help!

Kind regards
Timo
[ October 12, 2007: Message edited by: Timo Richter ]
 
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic