JAVA_HashMap運作_Set觀念補充_無序的潛藏陷阱


HashMap會去透過對應一組Key跟Value來做一個值的map存放。

key存在與不存在時的對應值回傳

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package hashmapapp;

import java.util.HashMap;

/**
 *
 * @author chous
 */
public class HashMapApp {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        HashMap<Integer,String> map = new HashMap<Integer,String>();
        
        map.put(5, "Five");
        map.put(8, "Eight");
        map.put(6, "Six");
        map.put(4, "Four");
        map.put(2, "Two");
        
        String resultIsExist = map.get(4);
        System.out.println(resultIsExist);
        String resultIsNotExist = map.get(1);
        System.out.println(resultIsNotExist);
    }
}



當透過 get 方法 要回傳key的對應值時
若不存在此key則預設會返回 null




存在重複key時的對應值返回
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package hashmapapp;

import java.util.HashMap;

/**
 *
 * @author chous
 */
public class HashMapApp {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        HashMap<Integer,String> map = new HashMap<Integer,String>();
        
        map.put(5, "Five");
        map.put(8, "Eight");
        map.put(6, "Six");
        String result = map.get(6);
        System.out.println(result);
        map.put(4, "Four");
        map.put(2, "Two");
        map.put(6, "Six2");
        String result2 = map.get(6);
        System.out.println(result2);
    }
}



當 HashMap物件中有重複key值時
其舊有的key對應value會被覆寫
因此不建議存有重複key ,容易出錯。

HashMap 的 遍歷尋訪

寫法1. 透過 for each keySet()


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package hashmapapp;

import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author chous
 */
public class HashMapApp {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        HashMap<Integer,String> map = new HashMap<Integer,String>();
        
        map.put(5, "Five");
        map.put(8, "Eight");
        map.put(6, "Six");
        map.put(4, "Four");
        map.put(2, "Two");
        map.put(6, "Six2");
        
        for(int key : map.keySet()){
            System.out.println(key + ": " + map.get(key));
        }
    }
}




寫法2. 透過for each entrySet()

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package hashmapapp;

import java.util.HashMap;
import java.util.Map;

/**
 *
 * @author chous
 */
public class HashMapApp {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here
        HashMap<Integer,String> map = new HashMap<Integer,String>();
        
        map.put(5, "Five");
        map.put(8, "Eight");
        map.put(6, "Six");
        map.put(4, "Four");
        map.put(2, "Two");
        map.put(6, "Six2");
        
        for(Map.Entry<Integer,String> entry: map.entrySet()){
            int key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + ": " + value);
        }
    }
}




無序的潛藏陷阱

這裡要注意 事實上 HashMap輸出的對應結果看似是由小至大排序
但其實它是隨機生成的!!!!
所以可能你重複了執行50到100次 看起來結果都像是幫你做好排序
但事實上並沒有
預設是無任何排序處裡的


這邊來嘗試下一個範例
跟剛剛上面一樣
只不過這次以 HashMap<String , Integer>
此格式
去做值的存放

很明顯是無任何依序排列呈現的

為何會有此種現象其實就在於無論是使用剛剛遍歷尋訪的
方法1. keySet()  或者方法2. entrySet()

它們的底層皆屬於 Set

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
     * Returns a {@link Set} view of the keys contained in this map.
     * The set is backed by the map, so changes to the map are
     * reflected in the set, and vice-versa.  If the map is modified
     * while an iteration over the set is in progress (except through
     * the iterator's own <tt>remove</tt> operation), the results of
     * the iteration are undefined.  The set supports element removal,
     * which removes the corresponding mapping from the map, via the
     * <tt>Iterator.remove</tt>, <tt>Set.remove</tt>,
     * <tt>removeAll</tt>, <tt>retainAll</tt>, and <tt>clear</tt>
     * operations.  It does not support the <tt>add</tt> or <tt>addAll</tt>
     * operations.
     *
     * @return a set view of the keys contained in this map
     */
    public Set<K> keySet() {
        Set<K> ks = keySet;
        if (ks == null) {
            ks = new KeySet();
            keySet = ks;
        }
        return ks;
    }




 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
/**
     * Returns a {@link Set} view of the mappings contained in this map.
     * The set is backed by the map, so changes to the map are
     * reflected in the set, and vice-versa.  If the map is modified
     * while an iteration over the set is in progress (except through
     * the iterator's own <tt>remove</tt> operation, or through the
     * <tt>setValue</tt> operation on a map entry returned by the
     * iterator) the results of the iteration are undefined.  The set
     * supports element removal, which removes the corresponding
     * mapping from the map, via the <tt>Iterator.remove</tt>,
     * <tt>Set.remove</tt>, <tt>removeAll</tt>, <tt>retainAll</tt> and
     * <tt>clear</tt> operations.  It does not support the
     * <tt>add</tt> or <tt>addAll</tt> operations.
     *
     * @return a set view of the mappings contained in this map
     */
    public Set<Map.Entry<K,V>> entrySet() {
        Set<Map.Entry<K,V>> es;
        return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
    }

Set 是無任何排序的  這也是它和List的最主要差異!!!

所以Set 的API官方文件也沒有提到能用index去取得特定元素的方法
這也可以說明 Set
不像 Array 和 List (LinkedList)這些資料型態是有依序擺放的!!!

















留言

這個網誌中的熱門文章

經得起原始碼資安弱點掃描的程式設計習慣培養(五)_Missing HSTS Header

經得起原始碼資安弱點掃描的程式設計習慣培養(三)_7.Cross Site Scripting(XSS)_Stored XSS_Reflected XSS All Clients

(2021年度)駕訓學科筆試準備題庫歸納分析_法規是非題