В чем разница между оператором == и оператором equals ()? (с хэш-кодом () ???) - PullRequest
4 голосов
/ 22 декабря 2010

Я изучил хэш-код более подробно и понял, что:

1. Если вы переопределяете equals (), вы также должны переопределить hashcode ().

2. Чтобы определить, являются ли 2 объекта одним и тем же объектом, используйте оператор ==

Учитывая эти 2 фактора, в Java я предполагал, что когда == operator используется для сравнения , если 2 экземпляра одинаковы или нет,

if(object1 == object2)

на самом деле делает

if(object1.hashcode() == object2.hashcode())

Но, похоже, я ошибся, выполнив тест ниже.

public class Main {

    public static void main(String[] args){
        Obj1 one = new Obj1();
        Obj1 two = new Obj1();
        //is this calling hashCode() in backend???
        if(one == two) {
            System.out.println("same");
        }
        else {
            System.out.println("nope");
        }
        //this is of course return true
        if(one == one) {
            System.out.println("one and one is same");
        }
    }
}

class Obj1 {
    @Override
    public int hashCode() {
        System.out.println("hashCode() is called");
        return 111;
    }
    @Override
    public boolean equals(Object another) {
        System.out.println("equals() is called");
        return false;
    }
}

В соответствии с тестом, который использует == operator и посмотрите, вызван ли equals() и не был.

Итак, мой вопрос: если == operator можно использовать для сравнения, если объект тот же или нет, то какой смысл переопределять e quals() и hashCode() метод для сравнения? Разве == operator не выполняет работу уже?

справка:

Переопределение hashCode () - это достаточно хорошо?

http://mindprod.com/jgloss/hashcode.html

http://download.oracle.com/javase/1.4.2/docs/api/java/lang/Object.html#equals(java.lang.Object)

Ответы [ 6 ]

5 голосов
/ 22 декабря 2010

оператор == определяет, указывают ли 2 ссылки на один и тот же объект.

Так

 Object o1 = new Object();
 Object o2 = o1;

 o1 == o2; //true

 o2 = new Object();

 o1 == o2 // false

Метод Object.equals () - это «как определить, равны ли 2 ссылки на объекты, которые не являются одним и тем же объектом?»

Если две ссылки указывают на один и тот же объект, оба

o1 == o2 
o1.equals(o2) 

должно быть правдой.

Но если o1 и o2 не являются одним и тем же объектом, они все равно могут быть логически равными. Для любого данного класса значение equals зависит от семантики объекта. Например, рассмотрим класс, где field1 и field2 задаются пользователем, но field3 вычисляется и имеет случайный элемент для вычисления. В этом случае может иметь смысл определять равные, чтобы зависеть только от field1 и field2, а не field3. Вот почему равенство необходимо.

4 голосов
/ 22 декабря 2010

== является тождеством.

.equals() является равенством.

.equals() по умолчанию используется только == (точно так же, как hashCode() по умолчанию System.identityHashCode(), но выможет переопределить их, если есть более осмысленный способ проверки на равенство. Как правило, это своего рода «структурное» равенство, т. е. все части this .equal() относятся ко всем частям that?

2 голосов
/ 22 декабря 2010

== (используется на объектах, а не на примитивных значениях) проверяет, являются ли 2 объекта фактически одним и тем же объектом;он сравнивает, действительно ли указатели указывают на одну и ту же область памяти.

.equals() определяется самим объектом.

String s1 = new String("Hello");
String s2 = new String("Hello");

boolean b1 = ( s1 == s2 ) ; // false: s1 and s2 point to different objects
boolean b2 = ( s1.equals(s2) ) ; // true: s1 and s2 both represent the same
                                 //       piece of text - "Hello"

.hashCode() - это прием оптимизации (в большинстве случаевего использование, во всяком случае). много кода в стандартных библиотеках предполагает, что если o1.equals(o2)==true, то o1.hashCode()==o2.hashCode(), а если o1.hashCode()!=o2.hashCode(), то o1.equals(o2)==false, чтобы работать быстрее.

НаиболееОчевидным примером такой оптимизации является класс HashMap .Это делает поиск объектов с использованием ключа действительно быстрым, но плохо работает, если hashCode и equals не работают должным образом для ключевых элементов.Фактически, это одна из причин того, что класс String является неизменяемым: если вы смогли изменить String (и, следовательно, изменить его hashCode), в то время как String был ключом в HashMap, то вы никогда бы не смогли найти его, поскольку вы в конечном итоге искали его не в том месте!

Другие ответы рекомендуют Effective Java от Joshua Bloch.Если вы задаете такие вопросы, то сейчас самое подходящее время в вашей карьере, чтобы купить книгу и прочитать ее от корки до корки.Стоит также перечитать его через год или два, когда вы забудете некоторые из них, и многое из этого будет иметь смысл ...

2 голосов
/ 22 декабря 2010

Если у вас еще нет копии; купите копию Эффективной Явы Джошуа Блохом.

Это фактический справочник для разработчиков Java, в котором содержится много информации по этой (и многим другим) темам.

1 голос
/ 22 декабря 2010

Большинство уже ответили, так что вот еще один поучительный пример:

String s1 = "foo";
String s2 = "foo";
System.out.println(s1 == s2); // true, because same reference (string pool)

String s3 = new String("foo");
String s4 = new String("foo");
System.out.println(s3 == s4); // false, because different reference
System.out.println(s3.equals(s4)); // true, because same value
0 голосов
/ 05 декабря 2014

== оператор -> проверяет погоду 2 ссылки указывают на один и тот же объект или нет. Если то же самое, вернуть true, иначе false.

equals( ) -> проверяет как ссылку, так и объект состояния. Состояние слуха означает данные объекта. В этом случае любой верен, он возвращает истину. В противном случае ложь. Но мы должны переопределить equals( ) в нашем определяемом пользователем объекте и написать соответствующий код.

Hashcode( ) -> hashCode объекта просто представляет случайное число, которое может использоваться JVM при сохранении / добавлении объектов в Hashsets, Hashtables или Hashmap.

Пример hashcode()

class TestHasChode
{
int i;
TestHasChode(int i)
{
this.i = i;
}

public static void main(String arg[])
{  
    //before overriding hashcode()  
TestHasChode t1 = new TestHasChode(100);   
TestHasChode t2 = new TestHasChode(110);

System.out.println(t1); //TestHasChode@45e41830  
System.out.println(t2); //TestHasChode@1f01b29  

TestHasChode t3 = new TestHasChode(100);  
TestHasChode t4 = new TestHasChode(100);  
System.out.println(t3); //TestHasChode@3a8721bd   
System.out.println(t4); //TestHasChode@7db81d4f

/*hashCode() of Object class implemented to return hashCode based on address of an object, but based
on our requirement we can override hashCode() to generate our own numbers as hashCodes*/

//after overriding hashcode()  
System.out.println(t3); //TestHasChode@64  
System.out.println(t4); //TestHasChode@64  
}  
public int hashCode(){
return i;
}  
}  
-->Example of equals()method      
class Student
{
String name;   
int rollno;   
Student(String name,int rollno)
{   
this.name = name;    
this.rollno = rollno;   
}   
public static void main(String arg[])
{       
    //before overrideng equals method    
Student s1 = new Student ("raju", 101);     
Student s2 = new Student ("giri", 102);     
Student s3 = new Student ("giri", 102);     
System.out.println(s1.equals(s2));//false    
System.out.println(s2.equals(s3));//false    
    //after overriding equals method    
System.out.println(s1.equals(s2));//false    
System.out.println(s2.equals(s3));//true-->hear overriding equals() checks state.so it is true.  
    //in string variables comparisition   
    String s4="hello";    
    String s5=new String("hello");    
    String s6=new String("hello");   
System.out.println(s4.equals(s5));//true--> because String class containg overridden equals method   
System.out.println(s5.equals(s6));//true-->even though differnet object reference but String class containg overridden equals method   

}     
public boolean equals(Object obj){   
String name1 = this.name;   
int rollno1 = this.rollno;   
Student s2 = (Student)obj;     
String name2 = s2.name;     
int rollno2 = s2.rollno;    
if(name1.equals(name2) && rollno1 == rollno2){   
return true;}   
else{     
return false;}  
}        
}
...