简体   繁体   中英

Java: Adding the same object in a NavigableSet rejected

Here's my code:

import java.util.*;

public class AnotherBackedCollectionsTest{

public static void main(String... args){

    Shape square = new Shape("square");
    Shape circle = new Shape("circle");
    Shape triangle = new Shape("triangle");

    NavigableSet<Shape> shapes = new TreeSet<Shape>();
    shapes.add(square);
    shapes.add(circle);
    shapes.add(triangle);

    System.out.println("New shape added? " +shapes.add(new Shape("square")));

    for(Shape s : shapes){
        System.out.println(s.getName());
    }


    Set<Shape> shapes2 = new HashSet<Shape>();
    shapes2.add(square);
    shapes2.add(triangle);
    shapes2.add(circle);

    System.out.println("New shape added? " +shapes2.add(new Shape("square")));

    for(Shape s : shapes2){
        System.out.println(s.getName());
    }

}

}

class Shape implements Comparable<Shape>{

private String name;

public Shape(String name){
    this.name = name;
}

public String getName(){
    return this.name;
}

public int compareTo(Shape shape){
    return this.name.compareTo(shape.getName());
}

}

And I get this output:

New shape added? false
circle
square
triangle
New shape added? true
triangle
square
square
circle

As you can see, I did not override the equals() method on the Shape object. What I found weird here was when I tried to add another Shape object with the name "square" in the NavigableSet , it rejected it somehow. Is is because Shape implements Comparable<T> so it used the overriden compareTo() method to determine method equality?

Basically, what I'm trying to ask is how did the NavigableSet determine that I was trying to add a duplicate object where, in fact, I did not override the equals() method.

TreeSet doesn't use equals() to compare elements. It uses the Comparable interface.

From the documentation :

a TreeSet instance performs all element comparisons using its compareTo (or compare ) method, so two elements that are deemed equal by this method are, from the standpoint of the set, equal.

As the documentation also notes, if you expect your set to obey the general Set contract, your must define equals() in a manner that's consistent with compareTo() :

The behavior of a set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Set interface.

On the other hand, HashSet does use equals() and hashCode() , and pays no attention to compareTo() .

This explains the difference in behaviour.

In a nutshell, to make your elements as widely compatible as possible, make sure to override equals() and hashCode() , and implement the Comparable interface.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM