1.有如下代码: java
class A{ public A(String str){ } } public class Test{ public static void main(String[] args) { A classa=new A("he"); A classb=new A("he"); System.out.println(classa==classb); } }
输出是什么?数组
答案:false多线程
即使是System.out.println(classa.equals(classb));也是false。 由于equals这个方法没有重写。并发
##关于重写equals方法:this
①为何要重写equals方法:spa
默认equals在比较两个对象时,是看他们是否指向同一个地址的。当一个类有本身特有的“逻辑相等”概念,好比一个People类,包含id和name两个属性,咱们想只要id和name同时相等的时候就断定为equal,可是不重写equals方法是作不到的。
package test01; class People{ int id; String name; public People(int id,String name){ this.id=id; this.name=name; } } public class t5 { public static void main(String[] args) { People people1=new People(123,"jia"); People people2=new People(123,"jia"); System.out.println(people1.equals(people2)); } }
这样输出为“false”线程
package test01; class People{ int id; String name; public People(int id,String name){ this.id=id; this.name=name; } public boolean equals(Object obj){ if(obj instanceof People){ People p=(People)obj; return p.id==id&&p.name.equals(name); } if(this==obj){ return true; } if(this==null) return false; return false; } } public class t5 { public static void main(String[] args) { People people1=new People(123,"jia"); People people2=new People(123,"jia"); System.out.println(people1.equals(people2)); } }
重写equals方法以后,这样的输出为true。code
可是看看下面一段代码: 对象
package test01; import java.util.HashMap; import java.util.Iterator; class People{ int id; String name; public int getId() { return id; } public String getName() { return name; } public People(int id,String name){ this.id=id; this.name=name; } public boolean equals(Object obj){ if(obj instanceof People){ People p=(People)obj; return p.id==id&&p.name.equals(name); } if(this==obj){ return true; } if(this==null) return false; return false; } } class Department{ String DepartmentName; int DepartmentId; public Department(int DepartmentId,String DepartmentName){ this.DepartmentId=DepartmentId; this.DepartmentName=DepartmentName; } public String getDepartmentName() { return DepartmentName; } public int getDepartmentId() { return DepartmentId; } } public class t5 { public static void main(String[] args) { HashMap<People,Department> map=new HashMap<People,Department>(); People people1=new People(123,"jia");
Department department1=new Department(11,"FinanceDepartment");
map.put(people1,department1);
People people2=new People(123,"jia");
Department department2=new Department(12,"MarketingDepartment");blog
map.put(people2,department2); People people3=null; System.out.println(people1.equals(people2)); Iterator it=map.keySet().iterator(); while(it.hasNext()){ People tmp=(People)it.next(); System.out.println(tmp.getName()+" "+tmp.getId()+" "+map.get (tmp).getDepartmentName() +" "+map.get(tmp).getDepartmentId()); } } }
我将两个People和Department做为HashMap中的key和value的值,代码中能够看出来,people1和people2的内容是彻底相同的,那么按照HashMap的性质,put数据进HashMap的时候当key值与map内的某一key值相同时,是将原来的value值覆盖掉的。可是,运行的结果是
因而可知,key值彻底相同,可是并无把第一个的value值覆盖掉。
先来看看HashMap中的put方法:
public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); int i = indexFor(hash, table.length); for (Entry<K,V> e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }
能够看到,在put中若是(其key的hashcod与map中key的hashcode相同,key值与map中key值相同(对于基础数据类型),key值equal map中的key值(String或者封装类型,引用类型))那么将覆盖其原有的value。
因此,缘由找到了,是由于people1和people2的hashcode不相同,致使没有覆盖。
在key,也就是value类中添加对hashcode的重写。
public int hashCode() { int result = 17; result = 37 * result + name.hashCode(); result = 37 * result + id; return result; }
或者简单的能够这样写:
public int hashCode(){ return 50; }
添加完对hashcode的重写以后,运行结果:
因此,通常对equals进行重写的时候,也要把hashcode重写!
2.hashMap跟hashTable的区别?
答:
HashTable和HashMap区别
①继承不一样。
public class Hashtable extends Dictionary implements Map public class HashMap extends AbstractMap implements Map
②
Hashtable 中的方法是同步的,而HashMap中的方法在缺省状况下是非同步的。在多线程并发的环境下,能够直接使用Hashtable,可是要使用HashMap的话就要本身增长同步处理了。
③
Hashtable中,key和value都不容许出现null值。
在HashMap中,null能够做为键,这样的键只有一个;能够有一个或多个键所对应的值为null。当get()方法返回null值时,便可以表示 HashMap中没有该键,也能够表示该键所对应的值为null。所以,在HashMap中不能由get()方法来判断HashMap中是否存在某个键, 而应该用containsKey()方法来判断。
④两个遍历方式的内部实现上不一样。
Hashtable、HashMap都使用了 Iterator。而因为历史缘由,Hashtable还使用了Enumeration的方式 。
⑤
哈希值的使用不一样,HashTable直接使用对象的hashCode。而HashMap从新计算hash值。
⑥
Hashtable和HashMap它们两个内部实现方式的数组的初始大小和扩容的方式。HashTable中hash数组默认大小是11,增长的方式是 old*2+1。HashMap中hash数组的默认大小是16,并且必定是2的指数。