Kaffetrinken
Kaffetrinken

Reputation: 67

TreeSet.contains() does not call overwritten equals

i have a problem with the contains() method of TreeSet. As I understand it, contains() should call equals() of the contained Objects as the javadoc says:

boolean java.util.TreeSet.contains(Object o): Returns true if this set contains the specified element. More formally, returns true if and only if this set contains an element e such that (o==null ? e==null : o.equals(e)).

What I try to do: I have a list of TreeSets with Result Objects that have a member String baseword. Now I want to compare each TreeSet with all Others, and make for each pair a list of basewords they share. For this, I iterate over the list once for a treeSet1 and a second time for a treeSet2, then I iterate over all ResultObjects in treeSet2 and run treeSet1.contains(ResultObject) for each, to see if treeSet1 contains a Result Object with this wordbase. I adjusted the compareTo and equals methods of the ResultObject. But it seems that my equals is never called. Can anyone explain me why this doesn't work?

Greetings, Daniel

    public static void getIntersection(ArrayList<TreeSet<Result>> list, int value){

          for (TreeSet<Result> treeSet : list){

    //for each treeSet, we iterate again through the list of TreeSet, starting at the TreeSet that is next
                //to the one we got in the outer loop
                for (TreeSet<Result> treeSet2 : list.subList((list.indexOf(treeSet))+1, list.size())){

                //so at this point, we got 2 different TreeSets 
                HashSet<String> intersection = new HashSet<String>();

                for (Result result : treeSet){  
                    //we iterate over each result in the first treeSet and see if the wordbase exists also in the second one                

//!!!
                    if (treeSet2.contains(result)){
                        intersection.add(result.wordbase);
                    }
                }
                if (!intersection.isEmpty()){
                    intersections.add(intersection);
                }
            }
        }


public class Result implements Comparable<Result>{

    public Result(String wordbase, double result[]){
        this.result = result;
        this.wordbase = wordbase;
    }

    public String wordbase;
    public double[] result;

    public int compareTo(DifferenceAnalysisResult o) {

        if (o == null) return 0;

        return this.wordbase.compareTo(o.wordbase);
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((wordbase == null) ? 0 : wordbase.hashCode());
        return result;
    }

//never called
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        DifferenceAnalysisResult other = (DifferenceAnalysisResult) obj;
        if (wordbase == null) {
            if (other.wordbase != null)
                return false;
        } else if (!wordbase.equals(other.wordbase))
            return false;
        return true;
    }   
}

Upvotes: 4

Views: 1861

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1499880

As I understand it, contains() should call equals() of the contained Objects

Not for TreeSet, no. It calls compare:

A NavigableSet implementation based on a TreeMap. The elements are ordered using their natural ordering, or by a Comparator provided at set creation time, depending on which constructor is used.

...

Note that the ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equals if it is to correctly implement the Set interface.

Your compareTo method isn't currently consistent with equals - x.compareTo(null) returns 0, whereas x.equals(null) returns false. Maybe you're okay with that, but you shouldn't expect equals to be called.

Upvotes: 12

Related Questions