ht-4 hashmap特性


一、hashmap底層原理:

 hashmap調用默認構造方法會產生一個默認底層是長度為16的Entry數組,首先調用key的hasCode()方法來得到一個整數, int hash = hash(key.hashCode());
 這個整數就是哈希碼,然后把哈希碼作為參數傳遞到hash()函數中來進行運算,即散列運算,得到一個int類型的散列值 int i = indexFor(hash, table.length); (transient Entry[] table;) 把散列值和數組的長度來進行運算,最終得到Entry對象要存放到數組的位置(下標)。 hashmap內部的結構是數組加單向鏈表結構,因為不同的key有可能計算出相同的散列值,根據散列值計算出來的存放到數組的下標會沖突(同一個下標值),此時, 如果鍵相同,散列值也一樣,說明是同一個對象,此時會將鍵所對應的舊值用新的鍵值覆蓋掉, 如果散列值一樣,鍵名不一樣,說明是不同的對象,此時會把鍵值對封裝成entry對象放到那個散列值對應的下標位置處, 原來那個entry對象會以鏈表形式鏈接在新創建的entry對象后面

二、hashmap常用方法:

 存值:public V put(K key, V value)

取值:public V get(Object key) 

獲取所有的鍵:public Set<K> keySet()

獲取所有的值: public Collection<V> values()    Returns a {@link Collection} view of the values contained in this map.

取鍵值對的set集合:public Set<Map.Entry<K,V>> entrySet()

 map集合大小:public int size()

 判斷map是否非空:public boolean isEmpty()

 三、示例:

 1 package com.iotek.map;
 2 
 3 import java.util.Collection;
 4 import java.util.HashMap;
 5 import java.util.Map;
 6 import java.util.Map.Entry;
 7 import java.util.Set;
 8 
 9 public class HashMapDemo1 {
10     public static void main(String[] args) {
11         Map<String, String> map = new HashMap<String, String>(); // 接口的引用變量指向實現類的對象
12         // 創建HashMap對象,也就是創建一個Map容器
13         map.put(null, "張三"); // 添加鍵值對元素
14         map.put(null, "李四"); // 有相同的鍵時,后面添加的鍵對應的值會覆蓋掉之前鍵對應的值
15         map.put("john", "李四");
16         map.put("rose", "玫瑰");
17         map.put("mary", "小紅");
18         System.out.println("1" + map);
19 
20         // 獲取map中所有鍵,返回的是一個Set容器,可以用迭代器對象或者foreach來進行輸出
21         Set<String> keys = map.keySet();
22         System.out.println("******輸出map容器中所有的鍵:");
23         for (String key : keys) {
24             System.out.print(key + " "); // 用String類型的變量key來遍歷keys容器
25         }
26 
27         // 獲取map中所有的值:使用map接口中的values方法,返回Collection接口的實現類
28         Collection<String> values = map.values();
29         System.out.println("\n******輸出map容器中所有的值:");
30         for (String value : values) {
31             System.out.print(value + " "); // 用String類型的變量value來遍歷values容器
32         }
33 
34         // 得到key的同時,得到key所對應的值
35         System.out.println("\n******用獲取的鍵來得到對應的值並輸出:");
36         for (String key : keys) {
37             System.out.print(key + "--" + map.get(key)); // 用String類型的變量key來遍歷keys容器
38         }
39         System.out.println("\nmap容器中鍵值對的個數是:" + map.size());
40         System.out.println("判斷map容器中是否為空:" + map.isEmpty());
41 
42         // map.entrySet()返回的是一個set容器,其中放的是map.Entry內部接口
43         /*
44          * 當我們調用put(key,value)方法時,首先會把key和value封裝到Entry這個靜態內部類中,
45          * 再把Entry對象添加到數組中(哈希表),所以我們想要獲取map中的所有鍵值對,只需要獲取
46          * 數組匯總所有的Entry,接下來調用Entry對象中的getKey 和getValue方法就能獲取鍵值對
47          * 以后想輸出HashMap容器中所有的鍵值對,都可以調用HashMap的 entrySet()方法就可以了!!!
48          */
49         Set<Entry<String, String>> entrys = map.entrySet();
50         System.out.println("使用map接口的entrySet()方法獲取map容器中所有的鍵值對:");
51         for (Entry<String, String> entry : entrys) {
52             System.out.println(entry.getKey() + "-" + entry.getValue());
53         }
54         map.clear();
55         System.out.println("判斷map容器中是否為空:" + map.isEmpty());
56 
57     }
58 
59 }

 

map中鍵是對象時,需要重寫對象的hash和equals方法:

 1 package com.iotek.map;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 
 6 public class HashMapDemo2 {
 7 
 8     /**
 9      * @param args
10      */
11     public static void main(String[] args) {
12         Map<Student, String> map = new HashMap<Student, String>();
13         map.put(new Student("jay", 20), "張三"); // 1
14         map.put(new Student("lisi", 30), "李四");// 2
15         map.put(new Student("rose", 20), "玫瑰");// 3
16         map.put(new Student("lisi", 30), "陳飛");// 4
17         System.out.println(map.size());
18         System.out.println(map.toString());
19 
20         /*
21          * Student類中不重寫hashCode() and
22          * equals()方法,此處map.size()值是4,即map中有4個封裝了鍵值對的Entry對象
23          * 重寫了hashCode()和equals()方法后,2和4語句里的學生對象將被判斷為同一個鍵名,因此2位置處的鍵值會被替換掉
24          * 這正是我們需要的,對象相同,應該判定為是同一個鍵,因此,這就是需要重寫hashCode()和equals()方法的原因
25          */
26     }
27 }
28 
29 class Student {
30     private String name;
31     private int age;
32 
33     @Override
34     public int hashCode() {
35         final int prime = 31;
36         int result = 1;
37         result = prime * result + age;
38         result = prime * result + ((name == null) ? 0 : name.hashCode());
39         return result;
40     }
41     /*
42      * 用source中的 Generate hashCode() and equals() 來 生成重寫的hashCode()方法和equals()方法
43      * 只要姓名和年齡相同的學生,那么這個學生對象產生的hashCode值和equals方法的值也是一樣的,
44      * 此時就可以認為是hashmap里放的是同一個對象,那么這兩個相同的Student對象作為鍵時,
45      * 后面添加的Student對象對應的鍵值應該要覆蓋掉前面添加的鍵值
46      */
47 
48     @Override
49     public boolean equals(Object obj) {
50         if (this == obj)
51             return true;
52         if (obj == null)
53             return false;
54         if (getClass() != obj.getClass())
55             return false;
56         Student other = (Student) obj;
57         if (age != other.age)
58             return false;
59         if (name == null) {
60             if (other.name != null)
61                 return false;
62         } else if (!name.equals(other.name))
63             return false;
64         return true; // 只有當姓名和年齡都一樣時,才返回一個true,表示是同一個對象
65     }
66 
67     public Student(String name, int age) {
68         super();
69         this.name = name;
70         this.age = age;
71     }
72 
73     public String getName() {
74         return name;
75     }
76 
77     public void setName(String name) {
78         this.name = name;
79     }
80 
81     public int getAge() {
82         return age;
83     }
84 
85     public void setAge(int age) {
86         this.age = age;
87     }
88 
89     @Override
90     public String toString() {
91         return "Student [name=" + name + ", age=" + age + "]";
92     }
93 
94 }

結果:

使用hashmap判斷數組中字符串出現的次數:
 1 package com.iotek.map;
 2 
 3 import java.util.HashMap;
 4 import java.util.Map;
 5 import java.util.Map.Entry;
 6 import java.util.Set;
 7 /**
 8  * 使用hashmap判斷數組中字符串出現的次數
 9  * @author Administrator
10  *
11  */
12 public class AccountStringDemo {
13 
14     public static void main(String[] args) {
15         String[] strs = {"zhangsan","zhangsan","wangwu","chenliu","chenliu","lilei","lilei"};
16         Map<String,Integer> data = AccountUtil.account(strs);
17         AccountUtil.printData(data);
18     }
19 
20 }
21 
22 class AccountUtil {
23     public static Map<String,Integer> account(String [] strs) {
24         Map<String,Integer> data = new HashMap<String, Integer>();
25         for(int i = 0; i < strs.length; i++) {
26             String str = strs[i];
27             if(data.get(str) == null) { 
28                 data.put(str, 1);
29                 //如果第一次統計到該字符串,將該字符串作為鍵名,其出現的次數作為鍵值,保存在map容器中
30             } else {
31                 //如果不是第一次捕獲到該字符串,則data.get(str)!=null,那么將鍵值加1,表示第二次讀取到該字符串
32                 data.put(str, data.get(str)+1);  
33             }
34         }
35         return  data; //將最終的hashmap容器,也就是data返回
36     }
37     
38     public static void printData(Map<String,Integer> data) {
39         //使用HashMap的EntrySet()方法,返回map容器:data中的所有鍵值對(全部封裝在Entry中),然后進行打印
40         Set<Entry<String, Integer>> entrys = data.entrySet();
41         for(Entry<String, Integer> entry : entrys) {
42             System.out.println("字符串" + entry.getKey() + "出現了" + entry.getValue() + "次");
43         }
44     }
45     
46 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM