2014-01-09 3 views
0

У меня есть Treeset, где люди сортируются с их деньгами, но равенство производится по имени. У меня есть jack и jackie с тем же названием «jackie», и они считаются равными. jack добавлен в Treeset, jackie нет. документация Javadoc на говорит:Почему деревья не могут найти этот элемент?

Возвращает истину, если этот набор содержит указанный элемент. Далее формально возвращает true тогда и только тогда, когда этот набор содержит элемент e такой, что (o == null? E == null: o.equals (e)).

К сожалению, линия

System.out.println(peoples.contains(jackie)); 

возвращает ложь, когда jackie.equals(jack) возвращает истину. Зачем ?

Вот полный код.

public class UsingSet { 


public static void main(String[] args) { 


     People jo = new People("Jo");  
     People jack = new People("Jackie"); 
     jack.setMoney(12); 
     People jim = new People("Jimmy"); 
     jim.setMoney(150); 
     People john = new People("John"); 

     TreeSet<People> peoples = new TreeSet<People>(); 
     peoples.add(jo); 
     peoples.add(jack); 
     peoples.add(jim); 
     peoples.add(john); 


     People jackie = new People("Jackie"); 
     System.out.println("equality ? "+(jackie.equals(jack))); 
     System.out.println(peoples.contains(jackie)); 

    } 
} 

class People extends Object implements Comparable<People> { 

    public static long maxCount() { 
     return 25000000000L; 
    } 

    String name; 
    Float money = 1000f; 

    public People(String name) { 
     super(); 
     this.name = name; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

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

    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     People other = (People) obj; 
     if (name == null) { 
      if (other.name != null) 
       return false; 
     } else if (!name.equals(other.name)) 
      return false; 
     return true; 
    } 

    @Override 
    public String toString() { 
     return name; 
    } 

    @Override 
    public int compareTo(People other) { 

     int result = this.money.compareTo(other.getMoney()); 
     if (result == 0){ 
      //finding a second criteria 
      return this.name.compareTo(other.getName());   
     }else{ 
      return result; 
     } 
    } 


    public float getMoney() { 
     return money; 
    } 

    public void setMoney(float money) { 
     this.money = money; 
    } 

} 

EDIT: Javadoc говорит о том, что TreeSet на основе природного порядка должны быть согласованы с equals()compareTo(). Treeset с Comparator не должен.

Так что я немного изменил подобный код:

Comparator<People> compareByMoney = new Comparator<People>() { 

    @Override 
    public int compare(People p1, People p2) { 
    int result = p1.money.compareTo(p2.getMoney()); 
    if (result == 0){ 
    //finding a second criteria 
    return p1.name.compareTo(p2.getName());  
    }else{ 
     return result; 
    }   
} 

};  

TreeSet<People> peoples = new TreeSet<People>(compareByMoney); 
    ... 
    System.out.println(peoples.contains(jackie)); //--> true 
+0

FYI, он печатает верно для меня. http://ideone.com/anwxoX – user2336315

+0

Я исправил последнюю строчку main: я тестирую System.out.println (народы.контейнеры (jackie)); и это неверно –

ответ

1

Jackie формально не equals к гнезду, так как они не имеют то же количество денег (обратите внимание, что ваш метод равных только проверяет имя, а не деньги).

Вы используете атрибут money, чтобы сравнить их в своем деревьях. Поскольку Джекки имеет 1000 денег и разъем имеет 12, они не то же самое для TreeSet и, следовательно, содержит возвращаемые ложь ..

Если вы

People jackie = new People("Jackie"); 
jackie.setMoney(12); 

вы будете, что он выводит верно для как, или aternatively, если ваш метод compareTo просто:

@Override 
    public int compareTo(People other) { 
     return this.name.compareTo(other.getName());  
    } 

Он также выдает true.

Для этого необходимо изменить метод equals, чтобы сравнить сумму money или просто используйте это имя в своем методе compareTo.

Если вы читали документ:

Обратите внимание, что порядок поддерживается с помощью набора (предоставляется ли или нет явного компаратора) должны быть совместимы с равным, если он является правильно реализовать Установите интерфейс.(См. Comparable или Comparator для точного определения соответствия с равными.) Это связано с тем, что интерфейс Set определен в терминах операции , но экземпляр TreeSet выполняет все сравнения элементов с помощью compareTo (или сравнения) метод, так что два элемента, которые считается равным этим методом, с точки зрения множества, равна

в соответствии:

естественное упорядочение для класса с, как говорят, чтобы быть совместимыми с равно тогда и только тогда, когда e1.compareTo (e2) == 0 имеет то же логическое значение как e1.equals (e2) для каждого e1 и e2 класса С

С вашего кода мы имеем:

System.out.println("equality ? "+(jackie.equals(jack))); //equality ? true 
System.out.println(jackie.compareTo(jack)); //1 

Естественный порядок вашего класса не согласуется с равными. Поэтому не ожидайте, что ваш treeSet будет иметь нормальное поведение.

+0

Да, мой CompareTo не связан с equals(), и я не хочу изменять это. Но javadoc говорит явно, что содержит основан на equals(). Я мог бы также использовать Компаратор для Treeset и удалить интерфейс Comparable для людей. –

+0

@NicolasZozol Ваш метод equals не согласуется с вашим естественным компаратором. Проверьте мое редактирование. – user2336315

+0

Отличный ответ :) ** должен быть совместим с равными ** - проблема. Таким образом, если 'compareTo() == 0', то' equals() 'должен возвращать true. Но это означает, что Treeset довольно ограничен. –

0

Я просто запустить свой код, и это Println «истинный»

+0

Это не ответ. добавьте его в раздел комментариев. –

+0

У меня нет разрешения для добавления комментария. – sambean

0

Пожалуйста, обратите внимание бинарное дерево кулак, чтобы узнать о причине

enter image description here

CompareTo() использует метод, чтобы вставить какой-либо элемент в дереве (метод не равенства()). гнездо и jackie с разной суммой денег. так как метод compartTo() не является одним и тем же объектом. и поскольку метод compareTo() возвращает false. поэтому содержит (метод) также возвращение ложного

People jackie = new People("Jackie"); 
    System.out.println("equality ? "+(jackie.equals(jack))); 
    System.out.println("compareTo ? "+(jackie.compareTo(jack))); 
    System.out.println(peoples.contains(jackie)); 

если ваш метод равенства() возвращает истинное, то ваш метод CompareTo() также должен показать такое же поведение.

0

Я думаю, вы не заметили, что ваш алгоритм не подходит для вашей цели.

ОК, вы добавляете jack и jackie в TreeSet. Джек получил name ="jackie" и money="12" Джеки получил name="jackie" и тому money= <defaultValue> ="1000"

Если переопределить метод equals в людях класса (в основном, это проверить имя 2 объекта), вы получили по этому пути вашего чека "equality ? "+(jackie.equals(jack)), это, очевидно, верно

Но, когда вы переопределить метод compareTo в классе людей, вы проверяете первые деньги между вашими 2 объектами, поэтому ранее вы объявляете jack и jackie без же денег значения атрибута. Действительно, они разные, потому что ваша проверка денег! = 0, а вторая проверка имени игнорируется.

Ну, если вы меняете: People jackie = new People("Jackie"); в People jackie = new People("Jackie"); jackie.setMoney(12);

Вы запускаете его, волшебство! консоли вывода:
equality ? true
true

Проблема решена чувак

Смежные вопросы