Why using custom Comparator to treeSet is breaking the equality of String objects?

Rishi :

I have written a comparator which is calculating consonants in a given string to compare 2 strings, but it is somehow making TreeSet think that 2 strings are equal (may be when they are of same size).

public class SortDiff {
public static void main(String[] s1) {

    List<String> list = Arrays.asList("century", "army", "spit", "twin", "frog", "guideline", "impulse",
            "distributor", "hallway", "appeal", "fitness", "pudding", "mild", "enter", "kitchen", "constitutional",
            "die", "condition", "morsel", "jealous", "colorful", "myth", "belly", "rugby", "valid", "shot",
            "locate", "preference", "representative", "chart", "prince", "think", "threshold", "health", "sweater",
            "volume", "poison", "lease", "toast", "diplomat", "trait", "cower", "slime", "handy", "example",
            "sanctuary", "board", "crash", "large", "attract", "censorship", "room", "license", "smoke", "roll",
            "taste", "inflate", "continuation", "establish", "fault", "gown", "dirty", "width", "qualify",
            "reference", "excitement", "vegetable", "wear", "confusion", "concept", "willpower", "snarl", "develop",
            "integration", "pie", "respectable", "fast", "limit", "shaft", "acceptance", "insert", "brown", "death",
            "effective", "ticket", "play", "highway", "lot", "tablet", "mother", "pier", "facility", "match",
            "animal", "sport", "laundry", "negligence", "white", "vat", "nuclear");
    System.out.println(list.size() + "=====");
    TreeSet<String> tree = new TreeSet<String>(new sortByConsonants());//
    int count = 0;
    for (String s : list) {
        count++;
        System.out.println(s);
        System.out.println(tree.add(s));
    }
    System.out.println("===>" + count);
    System.out.println(tree.size() + "=====");
    Iterator itr = tree.iterator();
    while (itr.hasNext()) {
        System.out.println(itr.next());
    }
}


}

This is the comparator class which I am passing to TreeSet.

class sortByConsonants implements Comparator<String>{

    public int compare(String a, String b) 
    { 

        return count(a,2)-count(b,2);
    } 
    public boolean equals(String a,String b) {

        return a.equals(b);

    }

    public int count(String line,int type) {
        int vowels = 0, consonants = 0, digits = 0, spaces = 0;

        line = line.toLowerCase();
        for(int i = 0; i < line.length(); ++i)
        {
            char ch = line.charAt(i);
            if(ch == 'a' || ch == 'e' || ch == 'i'
                || ch == 'o' || ch == 'u') {
                ++vowels;
            }
            else if((ch >= 'a'&& ch <= 'z')) {
                ++consonants;
            }
            else if( ch >= '0' && ch <= '9')
            {
                ++digits;
            }
            else if (ch ==' ')
            {
                ++spaces;
            }
        }

        if(type==1) {
            return vowels;
        }else {
            return consonants;
        }

    }

}

Can someone please look into it and find what mistake I am making!!

Goal : I want to sort strings based on count of consonants (Without use of library sort() method)

Edit : changed to comparator logic to

public int compare(String a, String b) 
    { 
        if(count(a,2)-count(b,2)==0) {
            return 1;
        }
        return count(a,2)-count(b,2);
    } 

Still not working!!

Edit = For this question TreeSet is not the right Data Structure, should use ArrayList.

Nicholas K :

Change your SortByConsonants to the following. (Note that class names should start with a capital letter)

class SortByConsonants implements Comparator<String> {

    public int compare(String a, String b) {
        if (count(a) - count(b) == 0) {
            return 1;
        }
        return count(a) - count(b);
    }

    public boolean equals(String a, String b) {
        return a.equals(b);
    }

    public int count(String line) {
        int consonants = 0;
        line = line.toLowerCase();
        for (int i = 0; i < line.length(); ++i) {
            char ch = line.charAt(i);
            if (ch != 'a' && ch != 'e' && ch != 'i' && ch != 'o' && ch != 'u') {
                consonants++;
            }
        }
        return consonants;
    }

}

Also, since we are just interested to sort based on the count of consonants there is no need to calculate the number of vowels, spaces, digits, etc. Furthermore, there is also no need of passing in another parameter type to the method count

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=147866&siteId=1