導航:首頁 > 編程語言 > java初始化hashmap

java初始化hashmap

發布時間:2023-02-03 01:40:32

java中,HashMap的創建流程是什麼

創建流程,指的是:
Map<String, String> mp = new HashMap<String, String>();
嗎?
就是創建一個HashMap對象,其中鍵的類型為String,值的類型也為String;
當然,鍵和值的類型也可以是其他的。例如,創建了一個類叫做Student,我們現在還有每一個學生的學號。那麼就可以建立一個Map<String, Student> 這樣的HashMap。通過這樣的方式,我們就可以利用學號來找到具體對應的學生。

⑵ Java中HashMap初始容量問題

這個問題可以跟蹤一下HashMap的源碼就知道了,根據輸入的初始化容量(門檻?)的值(先了解HashMap中容量和負載因子的概念,其實這個和HashMap確定存儲地址的演算法有關),先判斷是否大於最大容量,最大容量2的30次方,1<<30 =(1073741824),如果大於此數,初始化容量賦值為1<<30,如果小於此數,調用tableSizeFor方法 使用位運算將初始化容量修改為2的次方數,都是向大的方向運算,比如輸入13,小於2的4次方,那面計算出來桶的初始容量就是16.

publicHashMap(intinitialCapacity){
this(initialCapacity,DEFAULT_LOAD_FACTOR);
}
/**
*Constructsanempty<tt>HashMap</tt>withthespecifiedinitial
*capacityandloadfactor.
*
*@
*@paramloadFactortheloadfactor
*@
*ortheloadfactorisnonpositive
*/
publicHashMap(intinitialCapacity,floatloadFactor){
if(initialCapacity<0)
("Illegalinitialcapacity:"+
initialCapacity);
if(initialCapacity>MAXIMUM_CAPACITY)
initialCapacity=MAXIMUM_CAPACITY;
if(loadFactor<=0||Float.isNaN(loadFactor))
("Illegalloadfactor:"+
loadFactor);
this.loadFactor=loadFactor;
this.threshold=tableSizeFor(initialCapacity);
}

/**

* Returns a power of two size for the given target capacity.

*/

static final int tableSizeFor(int cap) {

int n = cap - 1;

n |= n >>> 1;

n |= n >>> 2;

n |= n >>> 4;

n |= n >>> 8;

n |= n >>> 16;

return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;

}

⑶ java中main函數中初始化一個hashmap對象

你這題不給20分以上 估計沒人給你寫 飄過先~

⑷ Java中HashMap和TreeMap的區別深入理解

HashMap底層是用數組做的,TreeMap是基於樹做的
這么做的結果就是HashMap的數據在不停的添加的時候效率會比較低,而對於查找的效率是比較快的,TreeMap對於添加的效率是比較高的但是對於查找的效率要相對比較低一些

這里簡單從底層說一下,我就不從具體的實現上說,只從數據結構和大致的原理上來補充一下我的答案。
HashMap這個類在存儲的時候,首先根據key來計算機將要存儲的key-value映射對存儲在數組的什麼位置上,當計算出位置後就把這個映射對存儲到這個位置上。當讀取的時候,首先根據key來計算出一個位置來,到數組的相應的位置上去讀取數據,如果沒有數據,則表示此Map中不存在該映射對,若存在則直接返回。說到這里就可以解釋一下為什麼對於不停地存儲的效率相對比較低了,首先在初始化的時候對於數組的長度給了一個初始的長度,當往這裡面添加數據達到一定的程度的時候就沒法繼續添加數據了,繼續添加數據的沖突就會增大,或者沒法添加數據(這里有一個衡量的量就是裝填因子,是指這個數組中的添加的數據的個數和數組長度的比值,在java中比較合理的裝填因子數是0.75),當數據添加到這個程度的時候不能不讓用戶繼續添加數據吧,總得解決繼續添加數據的問題啊,於是提出了解決方案,即開一個更大的數組,把當前上的每一個數據重新在更大的數組上計算位置,並把數據復制過去,這樣完成的數組的擴大,看完這個我們知道,這個過程是很耗時的,所以說對於不停的存儲數據時效率是比較低的。這里有沒有一個稍微好一點的解決方案或者說不需要進行數組的擴大嗎,我們能不能一開始在初始化的時候就把數組的空間開辟的足夠大,這樣就不用在存儲的過程進行復制了,可以嗎,答案是肯定的,java給我們提供了這個在初始化的時候的方式。但是,也是有問題的那就是我們的數據不夠多,就會造成空間的浪費。有沒有一個速度即快又不浪費空間的方式呢,解決方案也有一個,那就是在開始的時候我們就能很好的預測數據的規模,這樣我們在開始的時候按照相應的規模進行初始化,這樣就很好了,實際中我們是不能很好的預測這個規模的。於是對於這種情況提出了下一個解決方案TreeMap。
TreeMap是一個基於樹的存儲結構,學過數據結構的應該知道,樹的實現方式是基於指針實現的,在Java中是用引用模擬實現的,這里大家都知道,其實樹的讀取效率並不低,這里是相對於數組的順序查找來說的,但是與HashMap的查找方式相比就有了差距,HashMap是上來先問你在哪,直接就去取數據了,TreeMap需要遍歷,也就是需要挨個詢問你是我要的東西嗎,對比一下,是就返回,不是就繼續查找,於是查找的效率就低了,但是它解決了HashMap數組擴大的時候的效率問題,就是新添加的數據可以往裡面添加,不會出現復制的情況,這里就是由於模擬的指針的緣故實現的。
其實從總體來說這兩個各有利弊,我們在使用的時候需要根據實際的需要來選擇相應的類。

⑸ JAVA hashmap的用法

已經給樓主寫了個例子..

import java.util.HashMap;
import java.util.HashSet;

import java.util.Iterator;

public class HashMapTest {

public static void main(String[] args){
HashMap<String,Object> hm=new HashMap<String,Object>();

People p1=new People();
People p2=new People();
People p3=new People();
People p4=new People();

hm.put("People3", p1);
hm.put("People1", p2);
hm.put("People4", p3);
hm.put("People2", p4);

Iterator<String> it=hm.keySet().iterator();

while(it.hasNext()){
System.out.println(it.next());
}
}
}
class People {
private String name;
private int age;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}

運行了沒問題..

祝樓主早日成功!

⑹ HashMap底層實現原理剖析

Hashmap是一種非常常用的、應用廣泛的數據類型,最近研究到相關的內容,就正好復習一下。網上關於hashmap的文章很多,但到底是自己學習的總結,就發出來跟大家一起分享,一起討論。

1.HashMap的數據結構:在java 中 數據結構,最基本 也就兩種 一種數組 一種模擬指針。所有的數據結構都可以用這兩個基本結構來構造的,hashmap也不例外。Hashmap實際上是一個數組和鏈表的結合體。數組的默認長度為16,

2.hashMap源碼解析

static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // 初始化容量大小 

static final int MAXIMUM_CAPACITY = 1 << 30; ///容器最大值

static final float DEFAULT_LOAD_FACTOR = 0.75f; //載入影子

static final Entry[] EMPTY_TABLE = {}; //null 的hashMap

transient Entry[] table = (Entry[]) EMPTY_TABLE;///動態擴大容器時使用的一個hashMap

transient int size;//當前數據量

int threshold;//擴大容器時的大小 為 capacity * load factor

final float loadFactor;//使用率閥值,默認為:DEFAULT_LOAD_FACTOR

存取元素 :調用put方法

public V put(K key, V value) { 

//判斷當前table 為Null 第一次Put 

 if (table == EMPTY_TABLE) {

     inflateTable(threshold);  //初始化容器的大小

 }

 if (key == null) 

 return putForNullKey(value); //判斷當前key 為null 將Null key添加到數組的第一個位置

 int hash = hash(key); //將當前key進行hash 詳情見下方

 int i = indexFor(hash, table.length); //調用完hash演算法後,詳情見下方

 for (Entry e = table[i]; e != null; e = e.next) { //循環判斷當前數組下標為Entry的實體 將當前key相同的替換為最新的值

            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); //如果key都不同 則添加Entry.詳情見下方

        return null;

    }

hashMap的hash演算法剖析

final int hash(Object k) {

        int h = hashSeed;

        if (0 != h && k instanceof String) {  //判斷當前k是否為string 和

            return sun.misc.Hashing.stringHash32((String) k); //使用stringHash32演算法得出key   的hash值

        }

        h ^= k.hashCode(); //調用key的hashCode 得出值 後使用"或"運算符 

        h ^= (h >>> 20) ^ (h >>> 12);

        return h ^ (h >>> 7) ^ (h >>> 4);

前面說過HashMap的數據結構是數組和鏈表的結合,所以我們當然希望這個HashMap裡面的 元素位置盡量的分布均勻些,盡量使得每個位置上的元素數量只有一個,那麼當我們用hash演算法求得這個位置的時候,馬上就可以知道對應位置的元素就是我們要的,而不用再去遍歷鏈表,這樣就大大優化了查詢的效率。

一個十進制數32768(二進制1000 0000 0000 0000),經過上述公式運算之後的結果是35080(二進制1000 1001 0000 1000)。看出來了嗎?或許這樣還看不出什麼,再舉個數字61440(二進制1111 0000 0000 0000),運算結果是65263(二進制1111 1110 1110 1111),現在應該很明顯了,它的目的是讓「1」變的均勻一點,散列的本意就是要盡量均勻分布。使用上述演算法後 "1"就變得很均勻了。

我們用table[index]表示已經找到的元素需要存儲的位置。先判斷該位置上有沒有元素(這個元素是HashMap內部定義的一個類Entity, 基本結構它包含三個類,key,value和指向下一個Entity的next),沒有的話就創建一個Entity對象,在 table[index]位置上插入,這樣插入結束;如果有的話,通過鏈表的遍歷方式去逐個遍歷,看看有沒有已經存在的key,有的話用新的value替 換老的value;如果沒有,則在table[index]插入該Entity,把原來在table[index]位置上的Entity賦值給新的 Entity的next,這樣插入結束

    }

indexFor 返回當前數組下標 ,

static int indexFor(int h, int length) {

        return h & (length-1);

    }

那麼得到key 之後的hash如何得到數組下標呢 ?把h與HashMap的承載量(HashMap的默認承載量length是16,可以自動變長。在構造HashMap的時候也可以指定一個長 度。這個承載量就是上圖所描述的數組的長度。)進行邏輯與運算,即 h & (length-1),這樣得到的結果就是一個比length小的正數,我們把這個值叫做index。其實這個index就是索引將要插入的值在數組中的 位置。第2步那個演算法的意義就是希望能夠得出均勻的index,這是HashTable的改進,HashTable中的演算法只是把key的 hashcode與length相除取余,即hash % length,這樣有可能會造成index分布不均勻。

首先來解釋一下為什麼數組大小為2的冪時hashmap訪問的性能最高?

看下圖,左邊兩組是數組長度為16(2的4次方),右邊兩組是數組長度為15。兩組的hashcode均為8和9,但是很明顯,當它們和1110「與」的時候,產生了相同的結果,也就是說它們會定位到數組中的同一個位置上去,這就產生了碰撞,8和9會被放到同一個鏈表上,那麼查詢的時候就需要遍歷這個鏈表,得到8或者9,這樣就降低了查詢的效率。同時,我們也可以發現,當數組長度為15的時候,hashcode的值會與14(1110)進行「與」,那麼最後一位永遠是0,而0001,0011,0101,1001,1011,0111,1101這幾個位置永遠都不能存放元素了,空間浪費相當大,更糟的是這種情況中,數組可以使用的位置比數組長度小了很多,這意味著進一步增加了碰撞的幾率,減慢了查詢的效率! 

void addEntry(int hash, K key, V value, int bucketIndex) {

  //// 若HashMap的實際大小 不小於 「閾值」,則調整HashMap的大小

        if ((size >= threshold) && (null != table[bucketIndex])) {

            resize(2 * table.length);

            hash = (null != key) ? hash(key) : 0;

          //// 設置「bucketIndex」位置的元素為「新Entry」,// 設置「e」為「新Entry的下一個節點」

            bucketIndex = indexFor(hash, table.length);

        }

        createEntry(hash, key, value, bucketIndex);

    }

//將當前key 和value添加到Entry[]中

void createEntry(int hash, K key, V value, int bucketIndex) { 

        Entry e = table[bucketIndex];  //將第一個就得table 復制個新的entry 

        table[bucketIndex] = new Entry<>(hash, key, value, e); //將當前新的Entry 復制個table[bucketIndex]  舊的table[bucketIndex] 和新的table[buckIndex]之間用next關聯。第一個鍵值對A進來,通過計算其key的hash得到的index=0,記做:table[0] = A。一會後又進來一個鍵值對B,通過計算其index也等於0,現在怎麼辦?HashMap會這樣做: B.next = A ,table[0] = B,如果又進來C,index也等於0,那麼 C.next = B ,table[0] = C;這樣我們發現index=0的地方其實存取了A,B,C三個鍵值對,他們通過next這個屬性鏈接在一起

        size++; //容量加1

    }

以上就是HashMap添加元素時的過程解析

那麼如何get元素呢?

public V get(Object key) {

 if (key == null) return getForNullKey(); //當前key是否為null 如果為null值返回table[0]這個value

    Entry entry = getEntry(key);

        return null == entry ? null : entry.getValue();

    }

final EntrygetEntry(Object key) {

 if (size == 0) { return null; }  //判斷容量是否大於0 

 int hash = (key == null) ? 0 : hash(key); //對當前key 進行hash hash後得到一個值

 for (Entry e = table[indexFor(hash, table.length)]; //獲取當前Entry 循環遍歷

            e != null;

            e = e.next) {

            Object k;

            if (e.hash == hash &&

                ((k = e.key) == key || (key != null && key.equals(k))))

                return e;

        }

        return null;

    }

擴展問題:

1.當前我們的hashMap中越來越大的之後,"碰撞"就越來越明顯,那麼如何解決碰撞呢?擴容!

當hashmap中的元素個數超過數組大小capti*loadFactor時,就會進行數組擴容,loadFactor的默認值為0.75,也就是說,默認情況下,數組大小為16,那麼當hashmap中元素個數超過16*0.75=12的時候,就把數組的大小擴展為2*16=32,即擴大一倍,然後重新計算每個元素在數組中的位置,而這是一個非常消耗性能的操作,所以如果我們已經預知hashmap中元素的個數,那麼預設元素的個數能夠有效的提高hashmap的性能。比如說,我們有1000個元素new HashMap(1000), 但是理論上來講new HashMap(1024)更合適,不過上面annegu已經說過,即使是1000,hashmap也自動會將其設置為1024。 但是new HashMap(1024)還不是更合適的,因為0.75*1000 < 1000, 也就是說為了讓0.75 * size > 1000, 我們必須這樣new HashMap(2048)才最合適,既考慮了&的問題,也避免了resize的問題

HashMap的兩種遍歷方式

第一種

Map map = newHashMap();

Iterator iter = map.entrySet().iterator();

while(iter.hasNext()) {

Map.Entry entry = (Map.Entry) iter.next();

Object key = entry.getKey();

Object val = entry.getValue();

}

效率高,以後一定要使用此種方式!

第二種

Map map = newHashMap();

Iterator iter = map.keySet().iterator();

while(iter.hasNext()) {

Object key = iter.next();

Object val = map.get(key);

}

效率低,以後盡量少使用!

歸納

簡單地說,HashMap 在底層將 key-value 當成一個整體進行處理,這個整體就是一個 Entry 對象。HashMap 底層採用一個 Entry[] 數組來保存所有的 key-value 對,當需要存儲一個 Entry 對象時,會根據hash演算法來決定其在數組中的存儲位置,在根據equals方法決定其在該數組位置上的鏈表中的存儲位置;當需要取出一個Entry時,

也會根據hash演算法找到其在數組中的存儲位置,再根據equals方法從該位置上的鏈表中取出該Entry。

⑺ java的HashMap能不能在new的同時賦值,就像new String[]的時候賦初值一樣

好像是不行的吧。。

你舉例的是,String[](字元串數組),數組是可以在new的時候直接賦值。。但是Hashmap是集合類,集合好像沒見過這么用的,因為在集合中究竟存放什麼類型都尚未定義

⑻ 關於JAVA MAP怎麼初始化生成

首先你要理解 Map的基本結構,key-value

這里最外層的Map,key是String類型,value是ArrayList。ArrayList裡面放得又是Map,這個Map的key是String,value也是String。

importjava.util.ArrayList;
importjava.util.HashMap;
importjava.util.Map;

publicclassTest{
publicstaticvoidmain(String[]args){
Map<String,ArrayList<Map<String,String>>>topMap=newHashMap<>();

Stringkey1="map_key1";//topMap的第一個key
ArrayList<Map<String,String>>value1=newArrayList<>();//topMap的第一個value

//start
Map<String,String>strMap=newHashMap<>();
strMap.put("hello","你好");
strMap.put("thanks","謝謝");
value1.add(strMap);

value1.add(newHashMap<>());//添加一個空的Map
//end

topMap.put(key1,value1);//放入topMap

//以上start到end段的代碼是在往value1的ArrayList中填充數據
//不填充也可以放入到topMap中,就像下面這樣
topMap.put("emptyList",newArrayList<Map<String,String>>());
topMap.put("emptyList2",newArrayList<>());//jdk1.7及之後推薦這樣寫,省掉泛型描述。前面的newHashMap<>()、newArrayList<>()也是省掉了
}
}

⑼ java中hashmap的應用,本人小白,這題要咋搞

importjava.util.HashMap;
importjava.util.Map;

publicclasswork{
publicstaticvoidmain(String[]args){
classStudent{//定義內部類Student
privateStringnum;//學號
privateStringname;//名稱
privateintage;//年齡

Student(){
}//無參構造方法

Student(Stringnum,Stringname,intage){//有參構造方法
this.num=num;
this.name=name;
this.age=age;
}

publicStringgetNum(){
returnnum;
}

publicvoidsetNum(Stringnum){
this.num=num;
}

publicStringgetName(){
returnname;
}

publicvoidsetName(Stringname){
this.name=name;
}

publicintgetAge(){
returnage;
}

publicvoidsetAge(intage){
this.age=age;
}

@Override
publicStringtoString(){//復寫toString方法
return"學號:"+this.num+",姓名:"+this.name+",年齡:"+this.age;
}
}
Map<String,Student>staff=newHashMap<String,Student>();
Studentstudent1=newStudent("15H001","唐僧",40);//用有參構造方法創建一個學生
Studentstudent2=newStudent();//用無參構造方法創建一個學生
student2.setNum("15H002");
student2.setName("孫悟空");
student2.setAge(2000);
Studentstudent3=newStudent("15H003","豬八戒",1000);//用有參構造方法創建一個學生
staff.put(student1.getNum(),student1);//1號學生放入hashMap
staff.put(student2.getNum(),student2);//2號學生放入hashMap
staff.put(student3.getNum(),student3);//3號學生放入hashMap

System.out.println("3.根據key(學號)查找學號為15H003和15H004的學生,如果存在則輸出其學號、姓名、年齡信息,否則輸出相應的提示信息");
String[]nums={"15H003","15H004"};
for(inti=0;i<nums.length;i++){
System.out.println("查找學號:"+nums[i]);
Studentstudent=staff.get(nums[i]);
if(student!=null){//如果找到了
System.out.println("學號:"+student.getNum()+",姓名:"+student.getName()+",年齡:"+student.getAge());
}else{//如果沒有找到
System.out.println("學號:"+nums[i]+"的學生沒有擦尋到相關信息");
}
}

System.out.println("4.輸出所有學生的信息");
for(Map.Entry<String,Student>entry:staff.entrySet()){
Stringkey=entry.getKey();
Studentvalue=entry.getValue();
System.out.println("學號:"+key+",姓名:"+value.getName()+",年齡:"+value.getAge());
}

System.out.println("5.移除唐僧");
staff.remove("15H001");//根據唐僧的學號移除唐僧

System.out.println("6.把HashMap變成數組,並輸出每個數組元素的信息(學號、姓名、年齡)");
Object[]values=staff.values().toArray();
for(inti=0;i<values.length;i++){
Studentstudent=(Student)values[i];
System.out.println(student.toString());
}
}
}

⑽ java hashmap怎麼初始化

HashMap 是一種常用的數據結構,一般用來做數據字典或者 Hash 查找的容器。普通青年一般會這么初始化:
HashMap<String, String> map = new HashMap<String, String>();
map.put("name", "test");
map.put("age", "20");

看完這段代碼,很多人都會覺得這么寫太啰嗦了,文藝青年一般這么來了:
HashMap<String, String> map = new HashMap<String, String>() {
{
map.put("name", "test");
map.put("age", "20");
}
};

閱讀全文

與java初始化hashmap相關的資料

熱點內容
xshell連接linux命令 瀏覽:5
把多個文件夾的內容合並在一起 瀏覽:481
基於單片機的澆花系統設計ppt 瀏覽:683
卷積碼編解碼及糾錯性能驗證實驗 瀏覽:352
請在刪除驅動器之前暫停加密什麼意思 瀏覽:785
光催化pdf 瀏覽:98
java字元串包含某字元 瀏覽:526
ssm身份認證源碼 瀏覽:466
預排序遍歷樹演算法 瀏覽:671
加密裝置如何打開ping功能 瀏覽:478
python下載372 瀏覽:901
u盤子文件夾隱藏 瀏覽:296
本地誤刪svn文件夾 瀏覽:685
海康威視python通道名 瀏覽:241
如何用app覆蓋全部曲庫 瀏覽:602
變異布林源碼 瀏覽:686
表格加密設置列印區域 瀏覽:437
卡耐基pdf下載 瀏覽:924
現在最流行的單片機 瀏覽:89
機頂盒刷機源碼 瀏覽:987