首先,要明白到下面的一些知識點:
1、collection是hashmap和array的介面
2、hashmap中的元素是沒有次序的,而array是有的
3、hashmap轉化為array對象時,裡面元素的排列順序與用Iterator遍曆原hashmap時的順序一樣。
4、新建立的array對象與參數列表中的列表對象對應起來;collection與原HashMap對應起來(所謂:對應就是某個對象的修改會自動引起另外一個對象的改變)
下面談談怎麼將一個hashmap對象轉化為array對象
首先,將hashmap轉化為collection對象
通過:values()方法
為什麼可以這麼做:
留意到hashmap類,中有一個成員變數:
transient volatile Collection<V> values = null;
再留意hashmap類,中有一個成員函數:
public Collection<V> values() {
Collection<V> vs = values;
return (vs != null ? vs : (values = new Values()));
}
返回的正正是hashmap對象的value值。
說到這裡,應該可以留意到你現在手上拿的僅僅是一個collection對象,離我們的目標還有一步之遙。
為了使到一個collection對象變成一個array對象,我們使用以下的方法:
<T> T[] toArray(T[] a);
對於這個方法,我們有必要說明一下。並且舉一些例子來驗證一下我的理解。
首先,可以看看collection介面的源碼中關於<T> T[] toArray(T[] a);的訴述:
(英文還可以的同學建議直接看原版的介紹,因為本人的英語水平有限,可能翻譯得不是太理想。怕誤人子弟啊!)
/**
* Returns an array containing all of the elements in this collection;
* the runtime type of the returned array is that of the specified array.
* If the collection fits in the specified array, it is returned therein.
* Otherwise, a new array is allocated with the runtime type of the
* specified array and the size of this collection.
*
* <p>If this collection fits in the specified array with room to spare
* (i.e., the array has more elements than this collection), the element
* in the array immediately following the end of the collection is set to
* <tt>null</tt>. (This is useful in determining the length of this
* collection <i>only</i> if the caller knows that this collection does
* not contain any <tt>null</tt> elements.)
*
* <p>If this collection makes any guarantees as to what order its elements
* are returned by its iterator, this method must return the elements in
* the same order.
*
* <p>Like the {@link #toArray()} method, this method acts as bridge between
* array-based and collection-based APIs. Further, this method allows
* precise control over the runtime type of the output array, and may,
* under certain circumstances, be used to save allocation costs.
*
* <p>Suppose <tt>x</tt> is a collection known to contain only strings.
* The following code can be used to dump the collection into a newly
* allocated array of <tt>String</tt>:
*
* <pre>
* String[] y = x.toArray(new String[0]);</pre>
*
* Note that <tt>toArray(new Object[0])</tt> is identical in function to
* <tt>toArray()</tt>.
*
* @param a the array into which the elements of this collection are to be
* stored, if it is big enough; otherwise, a new array of the same
* runtime type is allocated for this purpose.
* @return an array containing all of the elements in this collection
* @throws ArrayStoreException if the runtime type of the specified array
* is not a supertype of the runtime type of every element in
* this collection
* @throws NullPointerException if the specified array is null
*/
上面的介紹大概是這個意思:
這個方法可以返回一個包含了調用這個方法的collection對象中所有元素的新隊列對象;而這個新的隊列對象中元素的類型是根據參數列表中的隊列對象的元素類型決定的。如果原來collection對象的元素個數不超過參數列表中的隊列對象的元素個數,就不會另外建立一個新的列表對象,而是將collection對象中的全部元素放到參數列表中的隊列對象去。否則,就會先建立一個元素類型與參數列表中的隊列對象一樣而元素個數與原collection元素一致的隊列對象,再賦值進去。另外,如果參數列表中的隊列對象元素個數超過原collection的,系統會用null元素將剩下來的位置填滿。
除此之外,新的array對象中的元素的排列順序與使用一個iterator遍曆原collection對象中的元素的順序一致。
和toArray()方法一樣,這個方法實現了將collection對象轉化為array對象。但是,比起toArray()方法,這個方法可以更加準確地控制新隊列對象的元素類型,並且可以在特定的情況下節約記憶體。因為,當參數列表中的隊列對象足夠大的時候,就不需要額外申請空間來儲存新的隊列對象,而是直接使用原來的空間就可以了。
例如,x是一個儲存string元素的collection對象。下面的代碼就展示了我們如何使用一個新分配空間的隊列對象來儲存一個collection對象:
String[] y = x.toArray(new String[0]);
注意:
toArray(new Object[0])和toArray()的作用一樣。
*
* @參數 a 通過隊列對象a的元素類型指定新轉化所得的隊列對象的元素類型。如果隊列對象a的元素不小於待轉化的collection對象的元素個數時,不需要另外分配記憶體空間,直接將原collection對象的元素都放進隊列對象a中去。
* @返回一個持有原collection對象所有元素的隊列對象
* @throws ArrayStoreException 元素類型衝突
* @throws NullPointerException 參數列表中的隊列對象為空白
實驗1:
目的:驗證參數列表中的隊列對象的元素個數,對是否重新分配空間,儲存新隊列對象的影響
源碼1:
HashMap<String, String>test=new HashMap<String, String>();
test.put("a","a's value");
test.put("b", "b's value");
String []test1=new String[3];
String[] test2=test.values().toArray(test1);
System.out.println("test1:");
System.out.println(test1.length);
for(String v:test1){
System.out.println(v);
}
System.out.println("test2:");
System.out.println(test2.length);
for(String v:test2){
System.out.println(v);
}
console:
test1:
3
b's value
a's value
null
test2:
3
b's value
a's value
null
分析:
對比上面可見:參數列表中的隊列對象test1和目標隊列對象test2都指向了新隊列對象,即他們共有了記憶體空間不用另外分配。又因為參數列表中的隊列對象test1的元素個數超過原collection對象的元素個數,所以在後面填充null元素。
源碼2:
HashMap<String, String>test=new HashMap<String, String>();
test.put("a","a's value");
test.put("b", "b's value");
String []test1=new String[1];
String[] test2=test.values().toArray(test1);
System.out.println("test1:");
System.out.println(test1.length);
for(String v:test1){
System.out.println(v);
}
System.out.println("test2:");
System.out.println(test2.length);
for(String v:test2){
System.out.println(v);
}
console:
test1:
1
null
test2:
2
b's value
a's value
分析:
對比上面可見:參數列表中的隊列對象test1沒有獲得任何元素,而test2中有。可見,已經分配了新的記憶體空間了。
實驗二:
目的:發現兩個隊列對象之間的對應關係;collection對象與原hashmap對象的對應關係;但是前後兩組對應對象之間不會相互影響
源碼:
HashMap<String, String>test=new HashMap<String, String>();
test.put("a","a's value");
test.put("b", "b's value");
String []test1=new String[2];
Collection<String>variable=test.values();
String[] test2=variable.toArray(test1);
variable.remove("b's value");
System.out.println("colletction object:"+variable.toString());
System.out.println("Hashmap object:"+test);
// test.values().toArray(test1);
System.out.println("test1:");
System.out.println(test1.length);
for(String v:test1){
System.out.println(v);
}
System.out.println("test2:");
System.out.println(test2.length);
for(String v:test2){
System.out.println(v);
}
test2[0]="kaiwii modify!";
System.out.println("test2:");
System.out.println(test2.length);
for(String v:test2){
System.out.println(v);
}
System.out.println("test1:");
System.out.println(test1.length);
for(String v:test1){
System.out.println(v);
}
System.out.println(test.toString());
System.out.println("whether test contain the modified value:"+test.containsValue("kaiwii modify!"));
console:
colletction object:[a's value]
Hashmap object:{a=a's value}
test1:
2
b's value
a's value
test2:
2
b's value
a's value
test2:
2
kaiwii modify!
a's value
test1:
2
kaiwii modify!
a's value
{a=a's value}
whether test contain the modified value:false