亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

多用多學之Java中的Set,List,Map詳解

 更新時間:2016年06月28日 10:21:30   投稿:jingxian  
下面小編就為大家?guī)硪黄嘤枚鄬W之Java中的Set,List,Map詳解。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧

很長時間以來一直代碼中用的比較多的數據列表主要是List,而且都是ArrayList,感覺有這個玩意就夠了。ArrayList是用于實現(xiàn)動態(tài)數組的包裝工具類,這樣寫代碼的時候就可以拉進拉出,迭代遍歷,蠻方便的。

也不知道從什么時候開始慢慢的代碼中就經常會出現(xiàn)HashMap和HashSet之類的工具類。應該說HashMap比較多一些,而且還是面試經典題,平時也會多看看。開始用的時候簡單理解就是個鍵值對應表,使用鍵來找數據比較方便。隨后深入了解后發(fā)現(xiàn)

這玩意還有點小奧秘,特別是新版本的JDK對HashMap的改成樹后,代碼都有點小復雜咯。

Set開始用的較少,只是無意中在一個代碼中發(fā)現(xiàn)一個TreeSet,發(fā)現(xiàn)這個類可以自帶順利,感覺蠻有點意思,才慢慢的發(fā)現(xiàn)這也是個好工具啊。

代碼寫的多了就感覺到基礎的重要性,所以在此寫一篇小文簡單的整理一下對集合的一些知識。

好了,簡單的整理一下:

•List:即是列表,支持數組、鏈表的功能,一般都是線性的
•Map:即是映射表,存儲的是鍵與值的對應關系
•Set:即是集合的意思,主要是用于排重數據及排序

先來看看List

List是用于存放線性數據的一種窗口,比如:用于數組的ArrayList和用于鏈表的LinkedList。

ArrayList

這是一個數組列表,不過提供了自動擴容的功能,實現(xiàn)List接口,外部操作都是通過接口申明的方法訪問,這樣即安全又方便。

ArrayList的關鍵就是自動擴容,在對象初始化時可以設定初始容量,也可以按默認的容量。如果對數組大小沒有特別明確可以不指定初始大小,如果明確的話可以指定一個大小,這樣減少動態(tài)擴容時產生的卡頓。說到這就要說一下擴容是怎么實現(xiàn)的了,看下面的代碼:

private void grow(int minCapacity) {

    // overflow-conscious code

    int oldCapacity = elementData.length;

    int newCapacity = oldCapacity + (oldCapacity >> 1);

    if (newCapacity - minCapacity < 0)

      newCapacity = minCapacity;

    if (newCapacity - MAX_ARRAY_SIZE > 0)

      newCapacity = hugeCapacity(minCapacity);

    // minCapacity is usually close to size, so this is a win:

    elementData = Arrays.copyOf(elementData, newCapacity);

  }

grow是在ArrayList在添加元素或者一些容易檢查時會觸發(fā)的一個方法。主要過程:

1、得到數組的長度,并對其進行右移,這樣就相當于oldCapacity/2,得到新的長度

2、如果這個長度小于最小容量那么直接就用最小容易

3、如果大于了最大容易則取一個最大值,這里會調用一個hugeCapacity方法,主要是比較minCapacity與MAX_ARRAY_SIZE的,如果minCapacity大于MAX_ARRAY_SIZE則取Integer.MAX_VALUE,否則就取MAX_ARRAY_SIZE,有意思的是MAX_ARRAY_SIZE取的是Integer.MAX_VALUE - 8;并不知道這樣做的意義是什么

4、最后就是調用一個復制方法將現(xiàn)有數復制到一個新的數組中。

因為有這個復制過程,如果數組比較大,那么老是觸發(fā)擴容當然就會出現(xiàn)卡頓的情況。所以如果一開始就知道最大值而且很容易增長到這個值,那么開始初始化時就指定大小會有一定的作用。

LinkedList

這是針對鏈表的工具類,鏈表的優(yōu)秀是添加刪除啥的比較快,但是查找會慢一些。

至于代碼好像也沒什么特別的,就是一串指針鏈接起來,當然Java中就使用對象來代替,建立一個Node的對象,Node本身指向了前一個Node和后一個Node,這就是鏈表的結構:

 private static class Node<E> {

    E item;

    Node<E> next;

    Node<E> prev;

 

    Node(Node<E> prev, E element, Node<E> next) {

      this.item = element;

      this.next = next;

      this.prev = prev;

    }

  }

然后用兩個Node指向頭和尾就完成了,下面的代碼:

/**

   * Pointer to first node.

   * Invariant: (first == null && last == null) ||

   *      (first.prev == null && first.item != null)

   */

  transient Node<E> first;

 

  /**

   * Pointer to last node.

   * Invariant: (first == null && last == null) ||

   *      (last.next == null && last.item != null)

   */

  transient Node<E> last;

看一個add操作:

/**

   * Links e as last element.

   */

  void linkLast(E e) {

    final Node<E> l = last;

    final Node<E> newNode = new Node<>(l, e, null);

    last = newNode;

    if (l == null)

      first = newNode;

    else

      l.next = newNode;

    size++;

    modCount++;

  }

過往就是:

1、獲取到最后的Node并放在l中

2、創(chuàng)建一個新的Node,將數據取到這個Node中,創(chuàng)建過程會將新Node的prev指向l,這樣就接上了鏈

3、然后將last指向這個新Node

4、然判斷l(xiāng)是否null,如果是null說明是空鏈表,新node就是第一個元素,這樣first也要指向newNode

5、如果不為空則將l的next指向newNode

6、累加計數器

刪除操作也是這種Node的前后Node指向移動操作。

再來看看Map

Map是鍵與值做一個映射表的應用,主要的實現(xiàn)類:HashMap,HashTable,TreeMap

HashMap和HashTable

使用hash算法進行鍵值映射的就是HashMap啦,HashTable是帶有同步的線程安全的類,它們兩主要的區(qū)別就是這個。原理也類似,都是通過桶+鏈來組合實現(xiàn)。桶是用來存Key的,而由于Hash碰撞的原因值需要用一個鏈表來存儲。

•桶的意義在于高效,通過Hash計算可以一步定位
•鏈表的意義在于存取重復hash的數據

具體的原理以前寫過一篇《學習筆記:Hashtable和HashMap》

只不過看JDK1.8的HashMap換了存儲結構,采用紅黑樹的結構,這樣可能是解決鏈表查找效率問題吧?具體沒有細研究。

TreeMap

看過TreeMap的代碼后發(fā)現(xiàn)還是使用的樹結構,紅黑樹。由于紅黑樹是有序的,所以自然帶排序功能。當然也可通過comparator來指定比較方法來實現(xiàn)特定的排序。

因為采用了樹結構存儲那么添加和刪除數據時會麻煩一些,看一下put的代碼:

public V put(K key, V value) {

    Entry<K,V> t = root;

    if (t == null) {

      compare(key, key); // type (and possibly null) check

 

      root = new Entry<>(key, value, null);

      size = 1;

      modCount++;

      return null;

    }

    int cmp;

    Entry<K,V> parent;

    // split comparator and comparable paths

    Comparator<? super K> cpr = comparator;

    if (cpr != null) {

      do {

        parent = t;

        cmp = cpr.compare(key, t.key);

        if (cmp < 0)

          t = t.left;

        else if (cmp > 0)

          t = t.right;

        else

          return t.setValue(value);

      } while (t != null);

    }

    else {

      if (key == null)

        throw new NullPointerException();

      @SuppressWarnings("unchecked")

        Comparable<? super K> k = (Comparable<? super K>) key;

      do {

        parent = t;

        cmp = k.compareTo(t.key);

        if (cmp < 0)

          t = t.left;

        else if (cmp > 0)

          t = t.right;

        else

          return t.setValue(value);

      } while (t != null);

    }

    Entry<K,V> e = new Entry<>(key, value, parent);

    if (cmp < 0)

      parent.left = e;

    else

      parent.right = e;

    fixAfterInsertion(e);

    size++;

    modCount++;

    return null;

  }

1、先是檢查根節(jié)點是否存在,不存在說明是第一條數據,直接作為樹的根

2、判斷是否存在比較器,如果存在則使用比較器進行查找數據的存放位置,如果比較器返回結果小于0取左,大于0取右,否則直接替換當前節(jié)點的值

3、如果不存在比較器則key直接與節(jié)點的key比較,比較和前面方法一樣

4、接下來就是在找到的parent上創(chuàng)建一個子節(jié)點,并放入左或者右子節(jié)點中

5、fixAfterInsertion是對節(jié)點進行著色

6、累加器處理

在remove操作時也會有點麻煩,除了刪除數據外,還要重新平衡一下紅黑樹。

另外,TreeMap實現(xiàn)了NavigableMap<K,V>接口,所以也提供了對數據集合的一些返回操作。

最后看看Set

Set主要是兩類應用:HashSet和TreeSet。

HashSet

字面意思很明確,使用了Hash的集合。這種集合的特點就是使用Hash算法存數據,所以數據不重復,存取都相對較快。怎么做到的呢?

public boolean add(E e) {

    return map.put(e, PRESENT)==null;

  }

原來是存在一個map對象中,再看map是個啥?

private transient HashMap<E,Object> map;

是個HashMap,了解HashMap的就明白,這樣的數據是不會重復的。因為存入時是鼗對象本身作為Key來存的,所以在HashMap中只會存在一份。

了解了這點其他的東西就非常明白了。

TreeSet

這個集合是用于對集合進行排序的,也就是除了帶有排重的能力外,還可以自帶排序功能。只不過看了TreeSet的代碼發(fā)現(xiàn),其就是在TreeMap的基礎實現(xiàn)的。更準確的說應該是NavigableMap的派生類。默認不指定map情況下TreeSet是以TreeMap為基礎的。

public TreeSet() {

    this(new TreeMap<E,Object>());

  }

所以,這里可能更關注的是TreeSet是如何排重呢?看一下add的方法吧:

public boolean add(E e) {

    return m.put(e, PRESENT)==null;

  }

和HashSet有點類似,都是基于Map的特性來實現(xiàn)排重。確實簡單而且有效。

以上就是小編為大家?guī)淼亩嘤枚鄬W之Java中的Set,List,Map詳解全部內容了,希望大家多多支持腳本之家~

相關文章

  • Spring MVC--攔截器實現(xiàn)和用戶登陸例子

    Spring MVC--攔截器實現(xiàn)和用戶登陸例子

    本文主要介紹了Spring MVC--攔截器實現(xiàn)和用戶登陸例子,具有很好的參考價值,下面跟著小編一起來看下吧
    2017-03-03
  • 深入了解Java核心類庫--String類

    深入了解Java核心類庫--String類

    這篇文章主要為大家詳細介紹了java String類定義與使用的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能給你帶來幫助
    2021-07-07
  • 詳解springmvc之json數據交互controller方法返回值為簡單類型

    詳解springmvc之json數據交互controller方法返回值為簡單類型

    這篇文章主要介紹了springmvc之json數據交互controller方法返回值為簡單類型,非常具有實用價值,需要的朋友可以參考下
    2017-05-05
  • SpringAOP+RabbitMQ+WebSocket實戰(zhàn)詳解

    SpringAOP+RabbitMQ+WebSocket實戰(zhàn)詳解

    這篇文章主要介紹了SpringAOP+RabbitMQ+WebSocket實戰(zhàn)詳解,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-11-11
  • MyBatis 多表操作的實現(xiàn)

    MyBatis 多表操作的實現(xiàn)

    這篇文章主要介紹了MyBatis 多表操作的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • Java中JWT的使用的詳細教程

    Java中JWT的使用的詳細教程

    JWT的本質就是一個字符串,它是將用戶信息保存到一個Json字符串中,然后進行編碼后得到一個JWT token,并且這個JWT token帶有簽名信息,接收后可以校驗是否被篡改,所以可以用于在各方之間安全地將信息作為Json對象傳輸,本文介紹了Java中JWT的使用,需要的朋友可以參考下
    2023-02-02
  • java理論基礎Stream?reduce實現(xiàn)集合元素歸約

    java理論基礎Stream?reduce實現(xiàn)集合元素歸約

    這篇文章主要為大家介紹了java理論基礎Stream?reduce實現(xiàn)集合元素歸約示例詳解有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步
    2022-03-03
  • jdk在centos中安裝配置圖文教程

    jdk在centos中安裝配置圖文教程

    這篇文章主要介紹了jdk在centos中安裝配置圖文教程,文中給出大家jdk下載地址,需要的朋友可以參考下
    2018-04-04
  • 用Java編程輸出萬年歷的功能實現(xiàn)

    用Java編程輸出萬年歷的功能實現(xiàn)

    這篇文章主要介紹了用Java編程輸出萬年歷的功能實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-05-05
  • Java 深入淺出掌握Collection單列集合Set

    Java 深入淺出掌握Collection單列集合Set

    Collection集合類是單列集合類的根接口,用來存儲一系列符合某種規(guī)則的元素。List接口和Set接口是Collection集合類的子接口,其中List接口的常用實現(xiàn)類有ArrayList類、Vector類和LinkedList類;Set接口的常用實現(xiàn)類有HashSet類和TreeSet類
    2021-11-11

最新評論