Java Collections HashMap、LinkedHashMap、HashSet

1. HashMap
2. LinkedHashMap
3. HashSet
4. HashSet 與 ArrayList執行效率比較

HashMap

  1. 可以有N個Key與Value,但一個map只會有一個key存在
  2. 型態可以根據初始化來決定
  3. 不會按順序排序
Map<String, Integer> map1 = new HashMap<>();
map1.put("k123", 0);
map1.put("k123", 0);
map1.put("f345", 1);
map1.put("a234", 2);
map1.put("b234", 4);
map1.put("c234", 3);
System.out.println();
for(String map: map1.keySet()) {
    System.out.print(map + ", ");
}
//資料沒按照put的順序排列
//打印f345, k123, b234, c234, a234, 
//Location為class
private Map<Integer, Location> locations = new HashMap<>();
public static void main(String[] args) {
    Map<String, Integer> tempExit = new HashMap<>();
    //新增map,
    locations.put(0, new Location(0,"data1", tempExit));
    //避免曝露,如下刪除後,如果曝露,變更參數後,則會影響內部資料
    tempExit.remove("S");
}

//Location 
//this.map = map; 如果這樣的話,外部數值變化,內部也會跟著變化
//避免曝露,內部需要改成這樣,外部數值變化,內部並不會改變
if(map != null) {
    this.map = new HashMap<>(map);
} else {
    this.map = new HashMap<>();
}

可以使用以下方式找到對應的key,以及讀取

//map -> Map<String, Integer> map;
if(map.containsKey("key1")) {
    //找到此key
    int data = map.get("key1")
}

遍歷Map

for(String map: mpas.keySet()) {
    System.out.print(map + ", ");
}

for(Map.Entry<String, Integer> map: exits.entrySet()) {
    System.out.println("key: " + map.getKey() + 
                        ", value: " + map.getValue());
}

Collections.unmodifiableMap禁止修改Map

可以利用return,限制是否禁止修改Map

public Map<String, Integer> getMap() {
    return Collections.unmodifiableMap(exits);
}

LinkedHashMap

Map<String, Integer> map1 = new LinkedHashMap<>();
map1.put("k123", 0);
map1.put("k123", 0);
map1.put("f345", 1);
map1.put("a234", 2);
map1.put("b234", 4);
map1.put("c234", 3);
System.out.println();
for(String map: map1.keySet()) {
    System.out.print(map + ", ");
}
//資料按照put的順序排列
//打印k123, f345, a234, b234, c234, 

其餘用法與HashMap相同

HashSet

使用方法與List相似,但只會有一個key存在,但主要判斷是否為相同是根據hashCode

但hashCode,主要是equals return true的時候,才會觸發

因此重寫hashCode就必須要重寫equals,反過來也是

如果把下方程式碼TestClass裡面的hashCode、equals兩個註解

會打印

Data2
Data1
Data2
Data1

如果沒註解,則打印

Data1
Data2

private static Set<TestClass> testMap = new HashSet<>();

public static void main(String[] args) {
TestClass temp = new TestClass("Data1");
testMap.add(temp);
temp = new TestClass("Data1");
testMap.add(temp);
temp = new TestClass("Data2");
testMap.add(temp);
temp = new TestClass("Data2");
testMap.add(temp);
for(TestClass testClass: testMap) {
System.out.println("\t" + testClass.getKey());
}
}
public class TestClass {
    private Key key;

    public TestClass(String name) {
        this.key = new Key(name);
    }

    //將hashCode、equals兩個註解,會有不一樣的結果
    @Override
    public int hashCode() {
        return this.key.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if(this == obj) {
            return true;
        }
        if(obj instanceof TestClass) {
            TestClass theObject = (TestClass) obj;
            return this.key.equals(theObject.key);
        }
        return false;
    }

    public Key getKey() {
        return key;
    }

    public static class Key {
        private String name;

        public Key(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }

        @Override
        public int hashCode() {
            return this.name.hashCode() + 57;
        }

        @Override
        public boolean equals(Object obj) {
            if(obj instanceof Key) {
                Key key = (Key) obj;
                if (this.name.equals(key.getName())) {
                    return true;
                }
            }
            return false;
        }

        @Override
        public String toString() {
            return this.name;
        }
    }
}

HashSet 與 List執行效率比較

當10000筆資料做contains時

耗時:HashSet(1ms) < ArrayList(229ms)

//    private static Set<TestClass> testMap = new HashSet<>();
private static List<TestClass> testMap = new ArrayList<>();
public static void main(String[] args) {
long startTime;
long endTime;
long executeTime;
TestClass temp;
for(int i=0;i<10000;i++) {
temp = new TestClass("Data" + i);
testMap.add(temp);
}

startTime = System.currentTimeMillis();
for(TestClass testClass: testMap) {
if(testMap.contains(testClass)) {
}
}
endTime = System.currentTimeMillis();
executeTime = endTime - startTime;
System.out.println("executeTime: " + executeTime + "ms");
//HashSet 1ms
//ArrayList 229ms
}

當100000筆,新增資料時

耗時:HashSet(58ms) > ArrayList(42ms)

    private static Set<TestClass> testMap = new HashSet<>();
//    private static List<TestClass> testMap = new ArrayList<>();
    public static void main(String[] args) {
        long startTime;
        long endTime;
        long executeTime;
        TestClass temp;

        startTime = System.currentTimeMillis();
        for(int i=0;i<10000;i++) {
            temp = new TestClass("Data" + i);
            testMap.add(temp);
        }
        endTime = System.currentTimeMillis();
        executeTime = endTime - startTime;
        System.out.println("executeTime: " + executeTime + "ms");
        //HashSet 25ms
        //ArrayList 23ms
    }

當100000筆,刪除資料時

耗時:HashSet(18ms) < ArrayList(490ms)

//    private static Set<TestClass> testMap = new HashSet<>();
    private static List<TestClass> testMap = new ArrayList<>();
    public static void main(String[] args) {
        long startTime;
        long endTime;
        long executeTime;
        TestClass temp;

        for(int i=0;i<10000;i++) {
            temp = new TestClass("Data" + i);
            testMap.add(temp);
        }
        startTime = System.currentTimeMillis();
        for(int i=0;i<10000;i++) {
            temp = new TestClass("Data" + i);
            testMap.remove(temp);
        }
        executeTime = endTime - startTime;
        System.out.println("executeTime: " + executeTime + "ms");
        //HashSet 18ms
        //ArrayList 490ms
    }

當100000筆,removeAll時

耗時:HashSet(69ms) < ArrayList(27252ms)

    private static Set<TestClass> testMap = new HashSet<>();
// private static List<TestClass> testMap = new ArrayList<>();
public static void main(String[] args) {
long startTime;
long endTime;
long executeTime;
TestClass temp;

startTime = System.currentTimeMillis();
for(int i=0;i<100000;i++) {
temp = new TestClass("Data" + i);
testMap.add(temp);
}
testMap.removeAll(testMap);
endTime = System.currentTimeMillis();
// startTime = System.currentTimeMillis();
// for(TestClass testClass: testMap) {
// if(testMap.contains(testClass)) {
// }
// }
// endTime = System.currentTimeMillis();
executeTime = endTime - startTime;
System.out.println("executeTime: " + executeTime + "ms");
//HashSet 69ms
//ArrayList 27252ms
}

整體看起來HashSet效率優於ArrayList


相關文章

訂閱Codeilin的旅程,若有最新消息會通知。

廣告

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com 標誌

您的留言將使用 WordPress.com 帳號。 登出 /  變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 /  變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 /  變更 )

連結到 %s

WordPress.com.

向上 ↑

%d 位部落客按了讚: