Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

guava-libraries: Is Objects.hashCode(Object[]) collision safe?

In looking at different options for overriding hashCode(), I was directed to Objects.hashCode(Object[]) in Google's guava-libraries (javadoc). The javadoc states that it delegates to Arrays.hashCode(Object[]). Is it safe to use this method in many different object types? Isn't this prone to hash collision, or is this not likely simply because containers usually only contain one type of object?

As a simple example, consider the following classes,

public class Student {
    private final String name;

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

    @Override
    public int hashCode() {
        return Objects.hashCode(name);
    }
}

public class Teacher {
    private final String name;

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

    @Override
    public int hashCode() {
        return Objects.hashCode(name);
    }
}

public class HashCodeDriver {
    public static void main(String[] args) {
        final String name = "moe";
        Student s = new Student(name);
        Teacher t = new Teacher(name);

        long studentHash = s.hashCode();
        long teacherHash = t.hashCode();
        System.out.println("studentHash=" + studentHash + " teacherHash=" + teacherHash);
        if(studentHash == teacherHash) {
            System.out.println("hash codes match");
        }
        else {
            System.out.println("hash codes don't match");
        }
    }
}

Output:

studentHash=108322 teacherHash=108322
hash codes match

The objects are two different types but are generating the same hash code. Isn't this a problem? Should I pass in the class as the first parameter to prevent this collision? For example,

public class Student {
    private final String name;

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

    @Override
    public int hashCode() {
        return Objects.hashCode(Student.class, name);
    }
}

public class Teacher {
    private final String name;

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

    @Override
    public int hashCode() {
        return Objects.hashCode(Teacher.class, name);
    }
}

Is this why the javadoc warns about only supplying a single object to this method? From the javadoc,

Warning: When a single object is supplied, the returned hash code does not equal the hash code of that object.

like image 531
John McCarthy Avatar asked May 27 '11 23:05

John McCarthy


People also ask

What is hashCode collision?

In computer science, a hash collision or clash is when two pieces of data in a hash table share the same hash value. The hash value in this case is derived from a hash function which takes a data input and returns a fixed length of bits.

What is the hashCode of an object?

A hash code is an integer value that is associated with each object in Java. Its main purpose is to facilitate hashing in hash tables, which are used by data structures like HashMap.

Can hashCode of two objects be same?

1) If two objects are equal (i.e. the equals() method returns true), they must have the same hashcode. 2) If the hashCode() method is called multiple times on the same object, it must return the same result every time. 3) Two different objects can have the same hash code.

What does hashCode mean in Java?

The hashCode() method is defined in Java Object class which computes the hash values of given input objects. It returns an integer whose value represents the hash value of the input object. The hashCode() method is used to generate the hash values of objects.


1 Answers

It's not a problem when 2 different objects of 2 different types have the same hash code.

Hopefully, when you are going to build your HashMap you are not going to mix Students and Teachers as the keys to that map. And even in the case when you want to do HashMap<Object, Object> you will be OK, because

assertFalse( new Teacher( "John Smith" ).equals( new Student( "John Smith" ) );

This is why it's important to override both hashCode and equals.

The only drawback of delegating to Arrays.hashCode(Object[]) may be that sometimes it may be too expensive from the performance point of view.

For example, in your case, this would be a much better hash method for either Teacher or Student.

@Override
public int hashCode() {
    return name.hashCode();
}
like image 145
Alexander Pogrebnyak Avatar answered Oct 19 '22 06:10

Alexander Pogrebnyak