Last active
May 16, 2017 09:43
-
-
Save zhugw/b5beb900ac101066c73e867e6dc9d9b2 to your computer and use it in GitHub Desktop.
The effect of an object with or without euqals and hashCode as a hashmap key
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package interview; | |
import org.junit.Test; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.InvocationTargetException; | |
import java.util.Arrays; | |
import java.util.HashMap; | |
import java.util.Map; | |
import static org.junit.Assert.*; | |
/** | |
* 面试题: | |
* 考察作为HashMap的key的对象有无复写equals和hashCode时的表现 | |
* Created by zhuguowei on 5/16/17. | |
*/ | |
public class HashMapTest { | |
@Test | |
public void test_StudentWithOutEqualAndHashCode() throws Exception { | |
StudentWithOutEqualAndHashCode student1 = new StudentWithOutEqualAndHashCode("zhangsan"); | |
StudentWithOutEqualAndHashCode student2 = new StudentWithOutEqualAndHashCode("zhangsan"); | |
assertFalse(student1 == student2); // false | |
assertFalse(student1.equals(student2)); // false | |
Map<StudentWithOutEqualAndHashCode, Integer> map = new HashMap<>(); | |
map.put(student1, 1); | |
map.put(student2, 2); | |
assertEquals(2,map.size()); // 2 | |
assertEquals(1,map.get(student1).intValue()); | |
assertEquals(2,map.get(student2).intValue()); | |
printTable(map); | |
} | |
@Test | |
public void test_StudentWithHashCode() throws Exception { | |
StudentWithHashCode student1 = new StudentWithHashCode("zhangsan"); | |
StudentWithHashCode student2 = new StudentWithHashCode("zhangsan"); | |
assertFalse(student1 == student2); // false | |
assertFalse(student1.equals(student2)); // false | |
HashMap<StudentWithHashCode, Integer> map = new HashMap<>(); | |
map.put(student1, 1); | |
map.put(student2, 2); | |
assertEquals(2,map.size()); // 2 | |
assertEquals(1,map.get(student1).intValue()); | |
assertEquals(2,map.get(student2).intValue()); | |
printTable(map); | |
Object[] table = getTable(map); | |
assertEquals(student1, getStudent(student1.hashCode(), table,0)); | |
assertEquals(student2, getStudent(student2.hashCode(), table,1)); | |
} | |
@Test | |
public void test_StudentWithHashCodeAndEquals() throws Exception { | |
StudentWithHashCodeAndEquals student1 = new StudentWithHashCodeAndEquals("zhangsan"); | |
StudentWithHashCodeAndEquals student2 = new StudentWithHashCodeAndEquals("zhangsan"); | |
assertFalse(student1 == student2); // false | |
assertTrue(student1.equals(student2)); // true | |
HashMap<StudentWithHashCodeAndEquals, Integer> map = new HashMap<>(); | |
map.put(student1, 1); | |
map.put(student2, 2); | |
assertEquals(1,map.size()); | |
assertEquals(2,map.get(student1).intValue()); | |
assertEquals(2,map.get(student2).intValue()); | |
printTable(map); | |
Object[] table = getTable(map); | |
assertEquals(student1, getStudent(student1.hashCode(), table,0)); | |
assertNull(getStudent(student1.hashCode(), table,1)); | |
} | |
private Student getStudent(int hashCode, Object[] table, int nextIndex) throws NoSuchFieldException, IllegalAccessException { | |
int i = (hashCode ^ (hashCode >>> 16)) & (16 - 1); | |
Object node = table[i]; | |
for (int j = 0; j < nextIndex; j++) { | |
Field nextField = node.getClass().getDeclaredField("next"); | |
nextField.setAccessible(true); | |
node = nextField.get(node); | |
} | |
if(node == null){ | |
return null; | |
} | |
Field keyField = node.getClass().getDeclaredField("key"); | |
keyField.setAccessible(true); | |
return (Student) keyField.get(node); | |
} | |
private void printTable(Map map) throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { | |
Object[] table = getTable(map); | |
System.out.println(Arrays.toString(table)); | |
} | |
private Object[] getTable(Map map) throws NoSuchFieldException, IllegalAccessException { | |
Field tableField = HashMap.class.getDeclaredField("table"); | |
tableField.setAccessible(true); | |
return (Object[]) tableField.get(map); | |
} | |
interface Student{} | |
static class StudentWithOutEqualAndHashCode implements Student{ | |
private String name; | |
public StudentWithOutEqualAndHashCode(String name) { | |
this.name = name; | |
} | |
public String getName() { | |
return name; | |
} | |
public void setName(String name) { | |
this.name = name; | |
} | |
} | |
static class StudentWithHashCode implements Student{ | |
private String name; | |
public StudentWithHashCode(String name) { | |
this.name = name; | |
} | |
public String getName() { | |
return name; | |
} | |
public void setName(String name) { | |
this.name = name; | |
} | |
@Override | |
public int hashCode() { | |
return 1; | |
} | |
} | |
static class StudentWithHashCodeAndEquals implements Student{ | |
private String name; | |
public StudentWithHashCodeAndEquals(String name) { | |
this.name = name; | |
} | |
public String getName() { | |
return name; | |
} | |
public void setName(String name) { | |
this.name = name; | |
} | |
@Override | |
public int hashCode() { | |
return 1; | |
} | |
@Override | |
public boolean equals(Object obj) { | |
return true; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment