Java:拒绝在NavigableSet中添加相同的对象

时间:2014-02-17 17:05:41

标签: java set

这是我的代码:

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());
}

}

我得到了这个输出:

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

如您所见,我没有覆盖equals()对象上的Shape方法。我在这里发现奇怪的是当我试图在Shape中添加名为“square”的另一个NavigableSet对象时,它以某种方式拒绝了它。是因为Shape implements Comparable<T>所以它使用重写compareTo()方法来确定方法相等吗?

基本上,我想问的是NavigableSet是如何确定我试图添加一个重复的对象,实际上我没有覆盖equals()方法。

1 个答案:

答案 0 :(得分:2)

TreeSet不使用equals()来比较元素。它使用Comparable接口。

来自documentation

  

TreeSet实例使用其compareTo(或compare)方法执行所有元素比较,因此从该方法的角度来看,通过此方法认为相等的两个元素是相等。

正如文档还指出的那样,如果您希望自己的集合遵守常规Set合同,则必须以与equals()一致的方式定义compareTo()

  

即使其排序与equals不一致,集合的行为也是明确定义的;它只是没有遵守Set接口的一般合同。

另一方面,HashSet确实使用equals()hashCode(),并且不关注compareTo()

这解释了行为上的差异。

简而言之,要使您的元素尽可能广泛兼容,请务必覆盖equals()hashCode(),并实施Comparable界面。