为什么每次添加新元素时ArrayList的hashCode()都会改变?

时间:2016-02-29 14:55:08

标签: java arraylist collections hashcode

根据我对ArrayList的理解,默认容量为10,当它超过10时,它将创建一个具有新容量的新对象,等等。

出于好奇,我输入以下程序来检查hashcode() ArrayList对象的public class TestCoreJava { public static void main(String [] args){ ArrayList al = new ArrayList(); for(int i=0;i<15;i++){ al.add("Temp"+i); System.out.println("Hashcode for "+i+" element "+al.hashCode()); } } }

ArrayList

根据上述情况,当我没有为ArrayList设置初始容量时,默认值为10。 因此,在添加第11个元素时,它将创建一个新对象并增加ArrayList的容量。

当我打印hashcode()对象的哈希码时,每次都会给出一个新的Hashcode for 0 element 80692955 Hashcode for 1 element -1712792766 Hashcode for 2 element -1476275268 Hashcode for 3 element 1560799875 Hashcode for 4 element 1220848797 Hashcode for 5 element -727700028 Hashcode for 6 element -1003171458 Hashcode for 7 element -952851195 Hashcode for 8 element 607076959 Hashcode for 9 element 1720209478 Hashcode for 10 element -6600307 Hashcode for 11 element -1998096089 Hashcode for 12 element 690044110 Hashcode for 13 element -1876955640 Hashcode for 14 element 150430735

以下是o / p:

hashcode()

根据默认容量的概念,直到第10个元素它应该打印相同的public class RangingService extends Service implements BeaconConsumer { private BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this); Handler handler; String b = ""; @Override public IBinder onBind(Intent arg0) { return null; } @Override public void onStart(Intent intent, int startId) { // Let it continue running until it is stopped. Log.d("Service", "Started"); beaconManager.bind(this); beaconManager.getBeaconParsers().clear(); beaconManager.getBeaconParsers().add(new BeaconParser(). setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25")); handler = new Handler(){ @Override public void handleMessage(Message msg) { // TODO Auto-generated method stub super.handleMessage(msg); Log.d("Checkpoint", "5 seconds have passed"); } }; new Thread(new Runnable(){ public void run() { // TODO Auto-generated method stub while(true) { try { startJob(); Log.d("Checkpoint", "Job has started"); Thread.sleep(5285); handler.sendEmptyMessage(0); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } }).start(); //return START_STICKY; } public void startJob() { Log.d("Checkpoint", "Starting job for realzies"); //onBeaconServiceConnect(); } @Override public void onDestroy() { super.onDestroy(); Log.d("Service", "Ended"); beaconManager.unbind(this); } @Override public void onBeaconServiceConnect() { Log.d("Checkpoint3", "Checkpoint3"); beaconManager.setRangeNotifier(new RangeNotifier() { @Override public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) { Log.d("Checkpoint1", "Checkpoint1"); if (beacons.size() > 0) { Log.d("Checkpoint2", "Checkpoint2"); //EditText editText = (EditText)RangingActivity.this.findViewById(R.id.rangingText); Beacon firstBeacon = beacons.iterator().next(); String a = "The first beacon " + firstBeacon.toString() + " is about " + firstBeacon.getDistance() + " meters away. RSSI = " + firstBeacon.getRssi(); Log.d("Service", a); //logToDisplay(a); } } }); try { beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null)); Log.d("Checkpoint4", "Checkpoint4"); } catch (RemoteException e) { } } ,因为在此之前不需要创建新对象,但事实并非如此。

3 个答案:

答案 0 :(得分:41)

hashCode的{​​{1}}是ArrayList中存储的所有元素的hashCode的函数,因此当容量发生变化时它不会改变,每当您添加或删除元素或以改变其hashCode的方式改变其中一个元素时,它都会发生变化。

这是Java 8实现(它实际上是在ArrayList中实现的):

AbstractList

BTW,这是public int hashCode() { int hashCode = 1; for (E e : this) hashCode = 31*hashCode + (e==null ? 0 : e.hashCode()); return hashCode; } 接口的hashCode()的Javadoc中出现的确切代码:

  

int java.util.List.hashCode()

     

返回此列表的哈希码值。列表的哈希码被定义为以下计算的结果:

List

答案 1 :(得分:4)

hashCode实施Listdefined in terms of the hashCode of its elements。这意味着,ArrayList成为符合List的实施方式,hashCode 必须在内容发生变化时进行更改。

更一般地说:对于可变对象,只要hashCode更改的方式不会使equal更改为先前的状态,Object就会发生变化。

您似乎假设它使用ArrayList的{​​{3}},但实际情况并非如此。

此外,即使hashCode未实现ArrayList,如果内部数组,ArrayList的默认哈希码(也称为default hashCode)也不会更改重新分配,因为response = self.kms_client.encrypt( KeyId = key_id, Plaintext = '1234' ) 对象本身保持不变,只是内部数组对象(你没有直接访问)将被替换为新的。

答案 2 :(得分:2)

通过查看the docs for hashCode

可以找到对此的解释
  

如果两个对象根据equals(Object)方法相等,则对两个对象中的每一个调用hashCode方法必须产生相同的整数结果。

ArrayList内容发生变化时,它还会更改其等于的其他对象。为了履行Object合同的这一部分,ArrayList要么在内容发生时进行hashCode更改,要么让ArrayList具有相同的hashCode { {1}}。为了使它有用,他们显然选择了前者。这可以通过查看List's docs来验证。

  

返回此列表的哈希码值。列表的哈希码是   定义为以下计算的结果:

 int hashCode = 1;
 for (E e : list)
     hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());
     

这确保了list1.equals(list2)暗示了这一点   list1.hashCode()== list2.hashCode(),用于任何两个列表,list1和list2,   根据Object.hashCode()的一般合同的要求。