views:

111

answers:

1

Hello,

I built a very simple custom Comparator, that I use with a TreeSet in order to sort Strings by length in that TreeSet.

I'm having trouble finding the reason why (s1.equals(s2)) returns false even when the two strings s1 and s2 contain the same value...

Eclipse "variables view" shows the letters are the same in both strings, but the "id" is different, I guess that's why equals returns False. By the way what is that id=" " representing ? some kind of pointer to the String object data ?

Here is the screenshot: http://yfrog.com/2rvariablesproblemj

public class MyComparator implements Comparator<String> {
    public int compare(String s1, String s2) {

        if(s1.length()<s2.length()) return -1;      
        else if (s1.length()>s2.length()) return 1; 
         return 0; 
        else if (s1.equals(s2)) return 0; //?? ALWAYS RETURNS FALSE
        else if (s1.toString().equals(s2.toString()))//SAME PROBLEM HERE (test)
        else return -1;
    }

    public boolean equals(String s) {
        if (this.equals(s)) return true;
        else return false;
    }
}

Now here is where I use this custom Comparator:

combinations = new TreeSet<String>(new MyComparator());

I fill combinations with several Strings, built with the substring() method. Because of the previously mentioned problem, combinations contains duplicates.

When I set NO custom Comparator for this TreeSet, there is no duplicate anymore (that's what I want) but it is sorted alphabetically which is normal but not my purpose.

Thanks in advance for your help on understanding the WHY of this...

Sébastien

+1  A: 

If what you're trying to do is sort by length but discard duplicates, the following should work.

import java.util.TreeSet;
import java.util.Comparator;
import java.util.Arrays;

public class MyComparator implements Comparator<String> {
    public int compare(String s1, String s2) {
        int s1Length = s1.length();
        int s2Length = s2.length();
        if (s1Length == s2Length) {
             return s1.compareTo(s2);
        }
        else {
              return s1Length - s2Length;
        }


    }

    public static void main(String[] args) {
    String[] strings = {"Hello", "Hello", "longer", "1", "477727357235", "hello"};



    TreeSet<String> set = new TreeSet<String>(new MyComparator());
        set.addAll(Arrays.asList(strings));

        // Won't be duplicates with substrings
        String s = "Hello World";
        set.add(s);
        for (int i = 0; i <= s.length(); i++) {
            String s1 = s.substring(0, i);
            set.add(s1);
        }
        // Still won't be a duplicate, even if we make a copy of the string.
        set.add(new String(s));

        System.out.println(set);
}
}

Output: [, 1, H, He, Hel, Hell, Hello, hello, Hello , longer, Hello W, Hello Wo, Hello Wor, Hello Worl, Hello World, 477727357235]

I82Much
You are absolutely right ! Thanks.My way of comparing was pretty ugly compared to your code. But anyway I haven't catched yet why it does not work...
Sebastien
Could you give us some sample words that don't match? I've tried your code and it seems to work. You don't need to call toString on strings, because they.. are already strings. But it won't hurt anything if you do. But it makes your second comparison to string.equals unnecessary... if their toStrings aren't equal, they are not equal. And you don't need that fall through - just return the result of them being equal (as I have done).
I82Much
Also, if this worked for you, please accept my answer as correct.
I82Much
I can't vote up your answer for now because a my low reputation, sorry.
Sebastien
I have not tested "independently" my buggy class, but only used it with String inputs generated by a "combination generator" method I use to find anagrams of a word.You can get more details on sample strings that are causing the problem by viewing the image I inserted in the initial question: http://yfrog.com/2rvariablesproblemj
Sebastien