2014-12-01 3 views
1

Я создал свой собственный класс с методом переопределенных равных, который просто проверяет, являются ли имена (атрибуты в классе) равными. Теперь я храню некоторые экземпляры этого класса в HashSet, чтобы в HashSet не было экземпляров с одинаковыми именами.Java HashSet содержит объект

Вопрос: Как проверить, содержит ли HashSet такой объект. .contains() не работает в этом случае, потому что он работает с методом .equals(). Я хочу проверить, действительно ли это тот же объект.

редактировать:

package testprogram; 

import java.util.HashSet; 
import java.util.Set; 

public class Example { 
    private static final Set<Example> set = new HashSet<Example>(); 
    private final String name; 
    private int example; 

    public Example(String name, int example) { 
     this.name = name; 
     this.example = example; 
     set.add(this); 
    } 

    public boolean isThisInList() { 
     return set.contains(this); 
     //will return true if this is just equal to any instance in the list 
     //but it should not 
     //it should return true if the object is really in the list 
    } 

    public boolean remove() { 
     return set.remove(this); 
    } 

    //Override equals and hashCode 
} 

К сожалению, мои английские навыки не очень хорошо. Пожалуйста, не стесняйтесь спрашивать, если вы не понимаете, что я имею в виду.

+0

Вы должны переопределить 'hashCode()' при переопределении 'equals()'. –

+0

Я знаю, но это не мой вопрос. – stonar96

+2

Это звучит скорее как плохой дизайн, который нужно решить, чем конкретная реализация. –

ответ

2

В вашей ситуации, единственный способ узнать, есть ли конкретный экземпляр объекта содержится в HashSet, чтобы перебирать содержимое из HashSet и сравнить идентификаторы объектов (используя оператор == вместо метода equals()).

Что-то вроде:

boolean isObjectInSet(Object object, Set<? extends Object> set) { 
    boolean result = false; 

    for(Object o : set) { 
    if(o == object) { 
     result = true; 
     break; 
    } 
    } 

    return result; 
} 
+0

Хорошо спасибо, я думаю, что это то, что я ищу. – stonar96

+0

Отлично! Примите ответ. – GreyBeardedGeek

0

Вам также придется переопределить метод hashCode.

0

HashSet contains использует метод equals для определения того, содержит ли объект - и дубликаты не сохраняются внутри HashSet.

Предполагая, что ваш equals и hashcode только с использованием name поля ...

HashSet<MyObject> objectSet = new HashSet<MyObject>(); 
MyObject name1Object = new MyObject("name1"); 

objectSet.add(new MyObject("name1")); 
objectSet.add(name1Object); 
objectSet.add(new MyObject("name2")); 
//HashSet now contains 2 objects, name1Object and the new name2 object 
//HashSets do not hold duplicate objects (name1Object and the new object with name1 would be considered duplicates) 

objectSet.contains(new MyObject("name1")) // returns true 
objectSet.contains(name1Object)   // returns true 
objectSet.contains(new MyObject("name2")) // returns true 
objectSet.contains(new MyObject("name3")) // returns false 

Если вы хотите, чтобы проверить, если объект в HashSet является точным объектом вы сравниваете вы должны вытащить его и сравнить его непосредственно с помощью ==

for (MyObject o : objectSet) 
{ 
    if (o == name1Object) 
    { 
     return true; 
    } 
} 

Если вы сделаете это большое за конкретные объекты, может быть проще использовать HashMap так что вам не придется перебирать т в списке, чтобы захватить определенный именованный объект. Может быть стоит посмотреть в для вас, потому что тогда вы могли бы сделать что-то вроде этого:

(objectMap.get("name") == myNameObject) // with a HashMap<String, MyNameObject> where "name" is the key string. 
+0

У меня есть другая ссылка, и я хочу проверить, все ли в списке. Ты знаешь, что я имею в виду? – stonar96

2

Путь, чтобы проверить, если объекты являются тем же объектом, сравнивая их с ==, чтобы увидеть, что ссылки на объекты равны.

Добрые Привет, Frank

+0

Спасибо, ваш ответ - ответ на мой вопрос. – stonar96

0

попробовать это .. Учитывая только одно свойство «имя» ваших объектов, чтобы сохранить уникальность.

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

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

Я сделал свой собственный класс с ПЕРЕОПРЕДЕЛЕНЫ равно метод, который просто проверяет, если имена (атрибуты в классе), равны.

Это нарушает договор .equals, и вы никогда не должны этого делать, независимо от того, насколько удобно.

Вместо этого, если вы хотите индексировать и искать элементы с помощью определенного атрибута, такого как имя, используйте HashMap<Name, YourType>, чтобы найти их. Кроме того, используйте TreeSet и передайте его Comparator, который сравнивает только имя. Затем вы можете удалить неправильный метод equals.

Есть три способа, а затем, если вы хотите, чтобы найти объекты ссылочного равенства:

  1. Ваших объекты не имеют никакого врожденного или полезное понятия равенства.

    Не применять equals. Оставьте его по умолчанию. Затем вы можете использовать HashSet для поиска ссылочного равенства, а также HashMap или TreeSet для индексации их по каким-либо конкретным атрибутам.

  2. Ваши объекты имеют полезное универсальное понятие равенства, но вы хотите найти эквивалентные экземпляры эффективно в любом случае.

    Это почти никогда не бывает. Однако вы можете использовать, например. Apache IdentityMap.

  3. Вы не заботитесь об эффективности.

    Используйте петлю for и == каждый элемент.

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