Grayden Hormes Grayden Hormes - 5 months ago 21
Java Question

jvm comparing String with StringBuffer.reverse() always fails

I had a problem where I was to find all he substrings of a string that are palindromes. Input would always be 1 word. The test input was aabaa. I decided to try be clever and make a string buffer of my substring then use the reverse method to compare with the original using String.equals. It didn't work.

import java.util.*

fun main(args: Array<String>) {
val scan = Scanner(System.`in`)
val input = scan.next()

val found = ArrayList<String>()

for (i in 0..input.length - 1) {
for (j in 0..input.length - i) {
val sub = input.substring(i, i + j)

if (!found.contains(sub)) {
// println(sub)
found.add(sub)
val rev = StringBuffer(sub).reverse()

if (sub.equals(rev)) {
println(rev)
}
}
}
}
}


When I uncomment the first print statement the output look like this using test input aabaa

a
aa
aab
aaba
aabaa
ab
aba
abaa
b
ba
baa


So I am getting the correct substrings, but the last if statement never resolves true and I don't know why this is.

Answer

sub is a String. rev is a StringBuffer. They can't be equal, since they don't even have the same type.

Additional notes:

  • don't use StringBuffer. Use StringBuilder. StringBuffer is needlessly synchronized, and should not be used anymore (just like Vector shouldn't be used and ArrayList should be instead).
  • for (i in 0..input.length - 1) can be written for (i in 0 until input.length) which is more elegant
  • input.substring(i, i + j) can't be right: at the end of the two loops, i would be length - 1, and j would be length - 1, and you would thus take a substring between length - 1 and 2 * length - 2.
  • to store unique results, use a HashSet, not an ArrayList. Calling contains() on a HashSet is O(1), whereas it's O(n) on an ArrayList.
  • in Kotlin, unlike in Java, you can use a == b to test if a is equal to b, even if a and b are references.