1. 程式人生 > 其它 >Map實現類結構情況---知識點(部分)

Map實現類結構情況---知識點(部分)

一:Map實現類結構情況

  • Map 雙列資料 用於儲存key-value對的資料 ----類似於高中講的函式 y=f(x)
  •      --HashMap:
            子類 --LinkedHashMap:
    
  •      -- TreeMap:
    
  •      --Hashtable:
           子類     --Properties:
    

區別

1.HashMap:作為我們的主要實現類,執行緒是不安全的,所以效率很高,可以存放null的key和value
2.Hashtable:作為我們古老的實現類 在1.2時候才有,執行緒是安全的,所以效率很低 是不能存放key和value的

public class MapTest {
    @Test
    public void test1(){
//        Map map = new HashMap();
        Hashtable map = new Hashtable();
        map.put(null,123);
        map.put(null,null);
        System.out.println();
    }
}

3.LinkedHashMap:能夠保證在遍歷的時候 是按照新增的順序進行輸出的,原因是:在原有的HashMap底層的基礎上,添加了一對指標
指向前一個元素,對於頻繁的進行遍歷操作,我們當前的LinkedHashMap要高於我們的HashMap。

4.TreeMap:可以按照新增的key-value進行排序,實現排序的遍歷 此時考慮key的自然排序,或者定製排序。底層使用對的是紅黑樹

注意:HashMap底層:資料+連結串列,僅限(jdk1.7之前)在(jdk8中) 是陣列+連結串列+紅黑樹

5.Properties :常用來處理配置檔案 key和value都是String 型別

面試題:

HashMap 的底層原理:

HashMap 和 Hashtable 的區別

CurrentHashMap 和Hashtable 異同(暫時不說)

二:Map結構的理解

  • Map中是無序的,不可以重複的,使用set進行存放所有的key,---->要求我們所在的類要重寫equals()和hashCode()方法(依HashMap舉例)
  • Map中的value是無序的,可以重複的,使用Collection存放所有的value,所在的類要重寫equals()方法
  • 一個鍵值對構成了一個Entry物件
  • Map中的entry:無序的,不可以重複的,使用set存放所有的entry

HashMap 的底層實現原理

  • 以jdk7為例
HashMap map = new HashMap();
  • 在例項化的時候底層建立了一個長度是16的一維陣列,Entry[] table

    ...可能已經執行多次的put()方法了
  map.put(key1,value1)往裡面新增資料 <br>
  • 1.首先先呼叫key1所在類的hashCode()方法,計算key1的雜湊值,此雜湊值經過某種演算法之後 得到Entry陣列中存放的位置
  • 2.如果此位置上資料為空,此時key1-value1新增成功 ---情況一
  • 3.如果此位置上資料不為空,(意味著此位置上存在一個或者多個數據(已連結串列的形式存在) 比較key1和已經存在的一個或者多個數據的雜湊值
    • 如果key1的雜湊值和已經存在的hash數值都不同,此時的key1-value1新增成功----情況二
    • 如果key1的雜湊值和已經存在的某個資料(key2-value2)雜湊值相同,繼續比較,呼叫key1所在類中equals(key2)方法,比較
    • 有兩種情況
    • 1.如果equals()返回的是false 則證明新增成功---情況三
    • 2.如果equals()返回的是true 使用value1替換value2

說明:情況二和情況三 此時的key1-value1和原來的資料以連結串列的方式儲存,再新增的時候會涉及的擴容問題,擴容原來的2倍,並將原來的複製過來

  • 在jdk8中相對於jdk7中的不同
  • 1.底層沒有長度為16的陣列
  • 2.jdk8中底層的陣列是Node[] 而非 Entry[]陣列
  • 3.首次呼叫put方法時候底層會建立長度為16的陣列
  • 4.jdk7中只有陣列+連結串列 在jdk8中;陣列+連結串列+紅黑樹
  • 當陣列某一個索引的位置上面的元素以連結串列形式的存在的資料個數>8 且當前陣列的長度>64的時候,此時索引上的陣列改為使用紅黑樹進行存放

Map的常用方法:

新增


import org.junit.Test;

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

public class MapTest {
    // 新增
    @Test
    public void test1(){
        Map map = new HashMap();
        map.put("AA",123);
        map.put(545,123);
        map.put("BB",123);
        System.out.println(map);
    }
}

    @Test
    public void test2(){
        Map map = new HashMap();
        map.put("AA",123);
        map.put("BB",123);

        Map map1 = new HashMap();
        map.put("CC",123);
        map.put("DD",123);
        map.putAll(map1);
        System.out.println(map);

    }

刪除

    @Test
    public void test3(){
        Map map = new HashMap();
        map.put("AA",123);
        map.put("BB",123);
        map.put("CC",123);
        map.put("DD",123);
        map.remove("DD");
        System.out.println(map);
    }
    //沒有的話返回值就是null

清空資料

 @Test
    public void test4() {
        Map map = new HashMap();
        map.put("AA", 123);
        map.put("BB", 123);
        map.put("CC", 123);
        map.put("DD", 123);
        map.clear();
        System.out.println(map);
    }
    //呼叫map.size()方法不會出現空指標異常,結果是0

查詢指定元素

   //元素查詢
    @Test
    public void test5() {
        Map map = new HashMap();
        map.put("AA", 123);
        map.put("BB", 123);
        map.put("CC", 123);
        map.put("DD", 123);
        System.out.println(map.get(45));
    }

判斷當前的map是否包含當前的key或者value

   @Test
    public void test6() {
        Map map = new HashMap();
        map.put("AA", 123);
        map.put("BB", 123);
        map.put("CC", 123);
        map.put("DD", 123);
        boolean isExist = map.containsKey("BB");
        System.out.println(isExist);
    }

是否包含指定的value方法

    @Test
    public void test7() {
        Map map = new HashMap();
        map.put("AA", 123);
        map.put("BB",789);
        map.put("CC", 456);
        map.put("DD", 123);
        boolean isExist= map.containsValue(123);
        System.out.println(isExist);
    }

元檢視操作方法

  • 遍歷所有的Key方法
@Test
    public void test8() {
        Map map = new HashMap();
        map.put("AA", 123);
        map.put("BB", 789);
        map.put("CC", 456);
        map.put("DD", 123);
        //遍歷所有的key
        Set set = map.keySet();
        Iterator iterator = set.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

遍歷所有的value

    @Test
    public void test9() {
        Map map = new HashMap();
        map.put("AA", 123);
        map.put("BB", 789);
        map.put("CC", 456);
        map.put("DD", 123);
        //遍歷所有的key
        Collection values = map.values();
        Iterator iterator = values.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

遍歷所有的key-value

    @Test
    public void test1_1() {
        Map map = new HashMap();
        map.put("AA", 123);
        map.put("BB", 789);
        map.put("CC", 456);
        map.put("DD", 123);
        Set set = map.entrySet();
        for (Object o : set) {
            System.out.println(o);
        }
    }

TreeMap兩種新增方式的使用

向TreeMap中新增key-value 要求key必須是由同一個類建立的物件,因為我們要按照key進行排序,不能按照Value進行排序,排序方式:自然排序,定製排序(使用Comparator然後按照想要的進行排序)

//自然排序
    @Test
    public void test1(){
        TreeMap map = new TreeMap();
        map.put("AA",123);
        map.put("BB",345);
        map.put("EE",567);
        Set set = map.entrySet();
        Iterator iterator = set.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }
    }

Properties說明


import org.junit.Test;

import java.io.FileInputStream;
import java.util.Properties;

public class PropertiesTest {
    @Test
    public void test() throws Exception {
        Properties properties = new Properties();
        //進行讀取
        FileInputStream is = new FileInputStream("jdbc.properties");
        properties.load(is);
//        properties.load(is);//載入流對應的檔案
        //讀取配置檔案
        String name = properties.getProperty("name");
        String password = properties.getProperty("password");
        System.out.println("姓名:"+name+"----密碼:"+password);
    }
}

Collections工具類的使用

Collections:操作Collection,Map的工具類

面試題Collections和Collection的區別:

  • Collection 是一個集合介面。它提供了對集合物件進行基本操作的通用介面方法。Collection介面在Java 類庫中有很多具體的實現。Collection介面的意義是為各種具體的集合提供了最大化的統一操作方式。
  • Collections 是一個包裝類。它包含有各種有關集合操作的靜態多型方法。此類不能例項化,就像一個工具類,服務於Java的Collection框架。
  • Collections 是一個包裝類,Collection 表示一組物件,這些物件也稱為 collection 的元素。一些 collection 允許有重複的元素,而另一些則不允許,一些 collection 是有序的,而另一些則是無序的。

常用方法

  • 反轉
import org.junit.Test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CollectionTest {
    @Test
    public void test() {
        //進行反轉
        List list = new ArrayList();
        list.add(123);
        list.add(433);
        list.add(235);
        list.add(876);
        System.out.println(list);
        Collections.reverse(list);
        System.out.println(list);
    }
}

  • 隨機化輸出
    @Test
    public void test1() {
        //隨機化輸出
        List list = new ArrayList();
        list.add(123);
        list.add(433);
        list.add(235);
        list.add(876);
        System.out.println(list);
        Collections.shuffle(list);
        System.out.println(list);
    }
  • 自然排序
@Test
    public void test2() {
        //自然排序
        List list = new ArrayList();
        list.add(123);
        list.add(433);
        list.add(235);
        list.add(876);
        System.out.println(list);
        Collections.sort(list);
        System.out.println(list);
    }

  • 交換索引位置上的元素
    @Test
    public void test3() {
        //交換索引位置上的元素
        List list = new ArrayList();
        list.add(123);
        list.add(433);
        list.add(235);
        list.add(876);
        System.out.println(list);
        Collections.swap(list,1,2);
        System.out.println(list);
    }
  • 返回指定集合中指定元素的出現次數
 @Test
    public void test4() {
        //交換索引位置上的元素
        List list = new ArrayList();
        list.add(123);
        list.add(433);
        list.add(235);
        list.add(235);
        list.add(876);
        System.out.println(list);
        Collections.frequency(list,235);
        System.out.println(list);
    }
  • 將src中的內容複製到dest中
    @Test
    public void test5() {
        //複製
        List list = new ArrayList();
        list.add(123);
        list.add(433);
        list.add(235);
        list.add(235);
        list.add(876);
//        System.out.println(list);
//        List dest = new ArrayList();
//        dest.add(3232);
//        dest.add(3232);
//        dest.add(3232);
//        dest.add(3232);
//        dest.add(3232);

        List dest = Arrays.asList(new Object[list.size()]);
        Collections.copy(dest,list);
        System.out.println(dest);
    }