欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java?HashSet添加?遍歷元素源碼分析

 更新時(shí)間:2022年07月08日 15:40:54   作者:趙妹兒  
這篇文章主要為大家詳細(xì)介紹了HashSet、HashMap底層添加、遍歷元素的機(jī)制,追蹤并分析源碼,文中的示例代碼講解詳細(xì),希望對(duì)大學(xué)有所幫助

HashSet 類圖

HashSet 簡(jiǎn)單說(shuō)明

1.HashSet 實(shí)現(xiàn)了 Set 接口

2.HashSet 底層實(shí)際上是由 HashMap 實(shí)現(xiàn)的

public HashSet() {
        map = new HashMap<>();
}

3.可以存放 null,但是只能有一個(gè) null

4.HashSet 不保證元素是有序的(即不保證存放元素的順序和取出元素的順序一致),取決于 hash 后,再確定索引的結(jié)果

5.不能有重復(fù)的元素

HashSet 底層機(jī)制說(shuō)明

HashSet 底層是 HashMap,HashMap 底層是 數(shù)組 + 鏈表 + 紅黑樹

模擬數(shù)組+鏈表的結(jié)構(gòu)

/**
 * 模擬 HashSet 數(shù)組+鏈表的結(jié)構(gòu)
 */
public class HashSetStructureMain {
    public static void main(String[] args) {
        // 模擬一個(gè) HashSet(HashMap) 的底層結(jié)構(gòu)
        // 1. 創(chuàng)建一個(gè)數(shù)組,數(shù)組的類型為 Node[]
        // 2. 有些地方直接把 Node[] 數(shù)組稱為 表
        Node[] table = new Node[16];
        System.out.println(table);
        // 3. 創(chuàng)建節(jié)點(diǎn)
        Node john = new Node("john", null);
        table[2] = jhon; // 把節(jié)點(diǎn) john 放在數(shù)組索引為 2 的位置
        Node jack = new Node("jack", null);
        jhon.next = jack; // 將 jack 掛載到 jhon 的后面
        Node rose = new Node("rose", null);
        jack.next = rose; // 將 rose 掛載到 jack 的后面
        Node lucy = new Node("lucy", null);
        table[3] = lucy; // 將 lucy 放在數(shù)組索引為 3 的位置
        System.out.println(table);

    }
}

// 節(jié)點(diǎn)類 存儲(chǔ)數(shù)據(jù),可以指向下一個(gè)節(jié)點(diǎn),從而形成鏈表
class Node{
    Object item; // 存放數(shù)據(jù)
    Node next; // 指向下一個(gè)節(jié)點(diǎn)
    public Node(Object item, Node next){
        this.item = item;
        this.next = next;
    }
}

HashSet 添加元素底層機(jī)制

HashSet 添加元素的底層實(shí)現(xiàn)

1.HashSet 底層是 HashMap

2.當(dāng)添加一個(gè)元素時(shí),會(huì)先得到 待添加元素的 hash 值,然后將其轉(zhuǎn)換成一個(gè) 索引值

3.查詢存儲(chǔ)數(shù)據(jù)表(Node 數(shù)組) table,看當(dāng)前 待添加元素 所對(duì)應(yīng)的 索引值 的位置是否已經(jīng)存放了 其它元素

4.如果當(dāng)前 索引值 所對(duì)應(yīng)的的位置不存在 其它元素,就將當(dāng)前 待添加元素 放到這個(gè) 索引值 所對(duì)應(yīng)的的位置

5.如果當(dāng)前 索引值 所對(duì)應(yīng)的位置存在 其它元素,就調(diào)用 待添加元素.equals(已存在元素) 比較,結(jié)果為 true,則放棄添加;結(jié)果為 false,則將 待添加元素 放到 已存在元素 的后面(已存在元素.next = 待添加元素)

HashSet 擴(kuò)容機(jī)制

1.HashSet 的底層是 HashMap,第一次添加元素時(shí),table 數(shù)組擴(kuò)容到 cap = 16threshold(臨界值) = cap * loadFactor(加載因子 0.75) = 12

2.如果 table 數(shù)組使用到了臨界值 12,就會(huì)擴(kuò)容到 cap * 2 = 32,新的臨界值就是 32 * 0.75 = 24,以此類推

3.在 Java8 中,如果一條鏈表上的元素個(gè)數(shù) 到達(dá) TREEIFY_THRESHOLD(默認(rèn)是 8),并且 table 的大小 >= MIN_TREEIFY_CAPACITY(默認(rèn)是 64),就會(huì)進(jìn)行 樹化(紅黑樹)

4.判斷是否擴(kuò)容是根據(jù) ++size > threshold,即是否擴(kuò)容,是根據(jù) HashMap 所存的元素個(gè)數(shù)(size)是否超過(guò)臨界值,而不是根據(jù) table.length() 是否超過(guò)臨界值

HashSet 添加元素源碼

/**
 * HashSet 源碼分析
 */
public class HashSetSourceMain {
    public static void main(String[] args) {
        HashSet hashSet = new HashSet();
        hashSet.add("java");
        hashSet.add("php");
        hashSet.add("java");
        System.out.println("set = " + hashSet);

        // 源碼分析
        // 1. 執(zhí)行 HashSet()
        /**
         * public HashSet() { // HashSet 底層是 HashMap
         *         map = new HashMap<>();
         *     }
         */

        // 2. 執(zhí)行 add()
        /**
         * public boolean add(E e) { // e == "java"
         *         // HashSet 的 add() 方法其實(shí)是調(diào)用 HashMap 的 put()方法
         *         return map.put(e, PRESENT)==null; // (static) PRESENT = new Object(); 用于占位
         *     }
         */

        // 3. 執(zhí)行 put()
        // hash(key) 得到 key(待存元素) 對(duì)應(yīng)的hash值,并不等于 hashcode()
        // 算法是 h = key.hashCode()) ^ (h >>> 16
        /**
         * public V put(K key, V value) {
         *         return putVal(hash(key), key, value, false, true);
         *     }
         */

        // 4. 執(zhí)行 putVal()
        // 定義的輔助變量:Node<K,V>[] tab; Node<K,V> p; int n, i;
        // table 是 HashMap 的一個(gè)屬性,初始化為 null;transient Node<K,V>[] table;
        // resize() 方法,為 table 數(shù)組指定容量
        // p = tab[i = (n - 1) & hash] 計(jì)算 key的hash值所對(duì)應(yīng)的 table 中的索引位置,將索引位置對(duì)應(yīng)的 Node 賦給 p
        /**
         * final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
         *                    boolean evict) {
         *         Node<K,V>[] tab; Node<K,V> p; int n, i; // 輔助變量
         *         // table 就是 HashMap 的一個(gè)屬性,類型是 Node[]
         *         // if 語(yǔ)句表示如果當(dāng)前 table 是 null,或者 table.length == 0
         *         // 就是 table 第一次擴(kuò)容,容量為 16
         *         if ((tab = table) == null || (n = tab.length) == 0)
         *             n = (tab = resize()).length;
         *         // 1. 根據(jù) key,得到 hash 去計(jì)算key應(yīng)該存放到 table 的哪個(gè)索引位置
         *         // 2. 并且把這個(gè)位置的索引值賦給 i;索引值對(duì)應(yīng)的元素,賦給 p
         *         // 3. 判斷 p 是否為 null
         *         // 3.1 如果 p 為 null,表示還沒(méi)有存放過(guò)元素,就創(chuàng)建一個(gè)Node(key="java",value=PRESENT),并把這個(gè)元素放到 i 的索引位置
         *         // tab[i] = newNode(hash, key, value, null);
         *         if ((p = tab[i = (n - 1) & hash]) == null)
         *             tab[i] = newNode(hash, key, value, null);
         *         else {
         *             Node<K,V> e; K k; // 輔助變量
         *             // 如果當(dāng)前索引位置對(duì)應(yīng)的鏈表的第一個(gè)元素和待添加的元素的 hash值一樣
         *             // 并且滿足下面兩個(gè)條件之一:
         *             // 1. 待添加的 key 與 p 所指向的 Node 節(jié)點(diǎn)的key 是同一個(gè)對(duì)象
         *             // 2. 待添加的 key.equals(p 指向的 Node 節(jié)點(diǎn)的 key) == true
         *             // 就認(rèn)為當(dāng)前待添加的元素是重復(fù)元素,添加失敗
         *             if (p.hash == hash &&
         *                 ((k = p.key) == key || (key != null && key.equals(k))))
         *                 e = p;
         *             // 判斷 當(dāng)前 p 是不是一顆紅黑樹
         *             // 如果是一顆紅黑樹,就調(diào)用 putTreeVal,來(lái)進(jìn)行添加
         *             else if (p instanceof TreeNode)
         *                 e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
         *             else {
         *                  // 如果 當(dāng)前索引位置已經(jīng)形成一個(gè) 鏈表,就使用 for 循環(huán)比較
         *                  // 將待添加元素依次和鏈表上的每個(gè)元素進(jìn)行比較
         *                  // 1. 比較過(guò)程中如果出現(xiàn)待添加元素和鏈表中的元素有相同的,比較結(jié)束,出現(xiàn)重復(fù)元素,添加失敗
         *                  // 2. 如果比較到鏈表最后一個(gè)元素,鏈表中都沒(méi)出現(xiàn)與待添加元素相同的,就把當(dāng)前待添加元素放到該鏈表最后的位置
         *                  // 注意:在把待添加元素添加到鏈表后,立即判斷 該鏈表是否已經(jīng)到達(dá) 8 個(gè)節(jié)點(diǎn)
         *                  // 如果到達(dá),就調(diào)用 treeifyBin() 對(duì)當(dāng)前這個(gè)鏈表進(jìn)行數(shù)化(轉(zhuǎn)成紅黑樹)
         *                  // 注意:在轉(zhuǎn)成紅黑樹前,還要進(jìn)行判斷
         *                  // if (tab == null || (n = tab.length) < MIN_TREEIFY_CAPACITY)
         *                  //        resize();
         *                  // 如果上面條件成立,先對(duì) table 進(jìn)行擴(kuò)容
         *                  // 如果上面條件不成立,才轉(zhuǎn)成紅黑樹
         *                 for (int binCount = 0; ; ++binCount) {
         *                     if ((e = p.next) == null) {
         *                         p.next = newNode(hash, key, value, null);
         *                         if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
         *                             treeifyBin(tab, hash);
         *                         break;
         *                     }
         *                     if (e.hash == hash &&
         *                         ((k = e.key) == key || (key != null && key.equals(k))))
         *                         break;
         *                     p = e;
         *                 }
         *             }
         *             // e 不為 null ,說(shuō)明添加失敗
         *             if (e != null) { // existing mapping for key
         *                 V oldValue = e.value;
         *                 if (!onlyIfAbsent || oldValue == null)
         *                     e.value = value;
         *                 afterNodeAccess(e);
         *                 return oldValue;
         *             }
         *         }
         *         ++modCount;
         *         // 擴(kuò)容:說(shuō)明判斷 table 是否擴(kuò)容不是看 table 的length
         *         // 而是看 整個(gè) HashMap 的 size(即已存元素個(gè)數(shù))
         *         if (++size > threshold)
         *             resize();
         *         afterNodeInsertion(evict);
         *         return null;
         *     }
         */
    }
}

HashSet 遍歷元素底層機(jī)制

HashSet 遍歷元素底層機(jī)制

1.HashSet 的底層是 HashMap,HashSet 的迭代器也是借由 HashMap 來(lái)實(shí)現(xiàn)的

2.HashSet.iterator() 實(shí)際上是去調(diào)用 HashMap 的 KeySet().iterator()

public Iterator<E> iterator() {
    return map.keySet().iterator();
}

3.KeySet() 方法返回一個(gè) KeySet 對(duì)象,而 KeySet 是 HashMap 的一個(gè)內(nèi)部類

public Set<K> keySet() {
    Set<K> ks = keySet;
    if (ks == null) {
        ks = new KeySet();
        keySet = ks;
    }
    return ks;
}

4.KeySet().iterator() 方法返回一個(gè) KeyIterator 對(duì)象,KeyIterator 是 HashMap 的一個(gè)內(nèi)部類

public final Iterator<K> iterator()     { return new KeyIterator(); }

5.KeyIterator 繼承了 HashIterator(HashMap的內(nèi)部類) 類,并實(shí)現(xiàn)了 Iterator 接口,即 KeyIteratorHashIterator 才是真正實(shí)現(xiàn) 迭代器 的類

final class KeyIterator extends HashIterator
    implements Iterator<K> {
    public final K next() { return nextNode().key; }
}

6.當(dāng)執(zhí)行完 Iterator iterator = HashSet.iterator; 之后,此時(shí)的 iterator 對(duì)象中已經(jīng)存儲(chǔ)了一個(gè)元素節(jié)點(diǎn)

  • 怎么做到的?
  • 回到第 4 步,KeySet().iterator() 方法返回一個(gè) KeyIterator 對(duì)象
  • new KeyIterator() 調(diào)用 KeyIterator 的無(wú)參構(gòu)造器
  • 在這之前,會(huì)先調(diào)用其父類 HashIterator 的無(wú)參構(gòu)造器
  • 因此,分析 HashIterator 的無(wú)參構(gòu)造器就知道發(fā)生了什么
/**
*         Node<K,V> next;        // next entry to return
*         Node<K,V> current;     // current entry
*         int expectedModCount;  // for fast-fail
*         int index;             // current slot
* HashIterator() {
*             expectedModCount = modCount;
*             Node<K,V>[] t = table;
*             current = next = null;
*             index = 0;
*             if (t != null && size > 0) { // advance to first entry
*                 do {} while (index < t.length && (next = t[index++]) == null);
*             }
*         }
*/
  • next、current、index 都是 HashIterator 的屬性
  • Node<K,V>[] t = table; 先把 Node 數(shù)組 talbe 賦給 t
  • current = next = null; currentnext 都置為 null
  • index = 0; index 置為 0
  • do {} while (index < t.length && (next = t[index++]) == null); 這個(gè) do-while 會(huì)在 table 中遍歷 Node 結(jié)點(diǎn)
  • 一旦 (next = t[index++]) == null 不成立 時(shí),就說(shuō)明找到了一個(gè) table 中的 Node 結(jié)點(diǎn)
  • 將這個(gè)節(jié)點(diǎn)賦給 next,并退出當(dāng)前 do-while 循環(huán)
  • 此時(shí) Iterator iterator = HashSet.iterator; 就執(zhí)行完了
  • 當(dāng)前 iterator 的運(yùn)行類型其實(shí)是 HashIterator,而 HashIterator 的 next 中存儲(chǔ)著從 table 中遍歷出來(lái)的一個(gè) Node 結(jié)點(diǎn)

7.執(zhí)行 iterator.hasNext

此時(shí)的 next 存儲(chǔ)著一個(gè) Node,所以并不為 null,返回 true

public final boolean hasNext() {
    return next != null;
}

8.執(zhí)行 iterator.next()

I.Node<K,V> e = next; 把當(dāng)前存儲(chǔ)著 Node 結(jié)點(diǎn)的 next 賦值給了 e

II.(next = (current = e).next) == null 判斷當(dāng)前結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)是否為 null

  • (a). 如果當(dāng)前結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)為 null,就執(zhí)行 do {} while (index < t.length && (next = t[index++]) == null);,在 table 數(shù)組中遍歷,尋找 table 數(shù)組中的下一個(gè) Node 并賦值給 next
  • (b). 如果當(dāng)前結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)不為 null,就將當(dāng)前結(jié)點(diǎn)的下一個(gè)結(jié)點(diǎn)賦值給 next,并且此刻不會(huì)去 table 數(shù)組中遍歷下一個(gè) Node 結(jié)點(diǎn)

III.將找到的結(jié)點(diǎn) e 返回

IV.之后每次執(zhí)行 iterator.next() 都像 (a)、(b) 那樣去判斷遍歷,直到遍歷完成

HashSet 遍歷元素源碼

/**
 * HashSet 源碼分析
 */
public class HashSetSourceMain {
    public static void main(String[] args) {
        HashSet hashSet = new HashSet();
        hashSet.add("java");
        hashSet.add("php");
        hashSet.add("java");
        System.out.println("set = " + hashSet);
        // HashSet 迭代器實(shí)現(xiàn)原理
        // HashSet 底層是 HashMap,HashMap 底層是 數(shù)組 + 鏈表 + 紅黑樹
        // HashSet 本身沒(méi)有實(shí)現(xiàn)迭代器,而是借由 HashMap 來(lái)實(shí)現(xiàn)的
        // 1. hashSet.iterator() 實(shí)際上是去調(diào)用 HashMap 的 keySet().iterator()
        /**
         * public Iterator<E> iterator() {
         *         return map.keySet().iterator();
         *     }
         */
        // 2. KeySet() 方法返回一個(gè) KeySet 對(duì)象,而 KeySet 是 HashMap 的一個(gè)內(nèi)部類
        /**
         * public Set<K> keySet() {
         *         Set<K> ks = keySet;
         *         if (ks == null) {
         *             ks = new KeySet();
         *             keySet = ks;
         *         }
         *         return ks;
         *     }
         */
        // 3. KeySet().iterator() 方法返回一個(gè) KeyIterator 對(duì)象,KeyIterator 是 HashMap的一個(gè)內(nèi)部類
        /**
         * public final Iterator<K> iterator()     { return new KeyIterator(); }
         */
        // 4. KeyIterator 繼承了 HashIterator(HashMap的內(nèi)部類) 類,并實(shí)現(xiàn)了 Iterator 接口
        // 即 KeyIterator、HashIterator 才是真正實(shí)現(xiàn) 迭代器的類
        /**
         * final class KeyIterator extends HashIterator
         *         implements Iterator<K> {
         *         public final K next() { return nextNode().key; }
         *     }
         */
        // 5. 當(dāng)執(zhí)行完 Iterator iterator = hashSet.iterator(); 后
        // 此時(shí)的 iterator 對(duì)象中已經(jīng)存儲(chǔ)了一個(gè)元素節(jié)點(diǎn)
        // 怎么做到的?
        // 回到第 3 步,KeySet().iterator() 方法返回一個(gè) KeyIterator 對(duì)象
        // new KeyIterator() 調(diào)用 KeyIterator 的無(wú)參構(gòu)造器
        // 在這之前,會(huì)先調(diào)用 KeyIterator 父類 HashIterator 的無(wú)參構(gòu)造器
        // 因此分析 HashIterator 的無(wú)參構(gòu)造器就知道發(fā)生了什么
        /**
         *         Node<K,V> next;        // next entry to return
         *         Node<K,V> current;     // current entry
         *         int expectedModCount;  // for fast-fail
         *         int index;             // current slot
         * HashIterator() {
         *             expectedModCount = modCount;
         *             Node<K,V>[] t = table;
         *             current = next = null;
         *             index = 0;
         *             if (t != null && size > 0) { // advance to first entry
         *                 do {} while (index < t.length && (next = t[index++]) == null);
         *             }
         *         }
         */
        // 5.0 next, current, index 都是 HashIterator 的屬性
        // 5.1 Node<K,V>[] t = table; 先把 Node 數(shù)組 table 賦給 t
        // 5.2 current = next = null; 把 current 和 next 都置為 null
        // 5.3 index = 0; index 置為 0
        // 5.4 do {} while (index < t.length && (next = t[index++]) == null);
        // 這個(gè) do{} while 循環(huán)會(huì)在 table 中 遍歷 Node節(jié)點(diǎn)
        // 一旦 (next = t[index++]) == null 不成立時(shí),就說(shuō)明找到了一個(gè) table 中的節(jié)點(diǎn)
        // 將這個(gè)節(jié)點(diǎn)賦給 next,并退出當(dāng)前 do while循環(huán)
        // 此時(shí) Iterator iterator = hashSet.iterator(); 就執(zhí)行完了
        // 當(dāng)前 iterator 的運(yùn)行類型其實(shí)是 HashIterator,而 HashIterator 的 next 中存儲(chǔ)著從 table 中遍歷出來(lái)的一個(gè) Node節(jié)點(diǎn)
        // 6. 執(zhí)行 iterator.hasNext()
        /**
         * public final boolean hasNext() {
         *             return next != null;
         *         }
         */
        // 6.1 此時(shí)的 next 存儲(chǔ)著一個(gè) Node,所以并不為 null,返回 true
        // 7. 執(zhí)行 iterator.next(),其實(shí)是去執(zhí)行 HashIterator 的 nextNode()
        /**
         * final Node<K,V> nextNode() {
         *             Node<K,V>[] t;
         *             Node<K,V> e = next;
         *             if (modCount != expectedModCount)
         *                 throw new ConcurrentModificationException();
         *             if (e == null)
         *                 throw new NoSuchElementException();
         *             if ((next = (current = e).next) == null && (t = table) != null) {
         *                 do {} while (index < t.length && (next = t[index++]) == null);
         *             }
         *             return e;
         *         }
         */
        // 7.1 Node<K,V> e = next; 把當(dāng)前存儲(chǔ)著 Node 節(jié)點(diǎn)的 next 賦值給了 e
        // 7.2 (next = (current = e).next) == null
        // 判斷當(dāng)前節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)是否為 null
        // a. 如果當(dāng)前節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)為 null
        // 就執(zhí)行 do {} while (index < t.length && (next = t[index++]) == null);
        // 再 table 數(shù)組中 遍歷,尋找 table 數(shù)組中的下一個(gè) Node 并賦值給 next
        // b. 如果當(dāng)前節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)不為 null
        // 就將當(dāng)前節(jié)點(diǎn)的下一個(gè)節(jié)點(diǎn)賦值給 next,并且此刻不會(huì)去 table 數(shù)組中遍歷下一個(gè) Node 節(jié)點(diǎn)
        // 7.3 將找到的節(jié)點(diǎn) e 返回
        // 7.4 之后每次執(zhí)行 iterator.next(),都像 a、b 那樣去判斷遍歷,直到遍歷完成
        Iterator iterator = hashSet.iterator();
        while (iterator.hasNext()) {
            Object next =  iterator.next();
            System.out.println(next);
        }
    }
}

到此這篇關(guān)于Java HashSet添加 遍歷元素源碼分析的文章就介紹到這了,更多相關(guān)HashSet添加 遍歷元素內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java浮點(diǎn)類數(shù)字運(yùn)算方式

    Java浮點(diǎn)類數(shù)字運(yùn)算方式

    在進(jìn)行浮點(diǎn)數(shù)的加減運(yùn)算時(shí),直接使用+和-可能會(huì)引入精度誤差,為了比較浮點(diǎn)數(shù),可以使用Double的compareTo()方法,或者通過(guò)定義一個(gè)容差值(Epsilon)來(lái)判斷兩個(gè)浮點(diǎn)數(shù)是否相等,此外,Double.compare()方法也能比較兩個(gè)double值
    2024-10-10
  • mybatis集成到spring的方式詳解

    mybatis集成到spring的方式詳解

    這篇文章主要介紹了mybatis是如何集成到spring的,將mybatis集成到spring之后,就可以被spring的ioc容器托管,再也不用自己創(chuàng)建SqlSessionFactory?、打開SqlSession等操作,本文結(jié)合實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-05-05
  • Mybatis創(chuàng)建逆向工程的步驟

    Mybatis創(chuàng)建逆向工程的步驟

    Mybatis逆向工程是一個(gè)自動(dòng)生成Mybatis Mapper接口、XML文件和Java實(shí)體類的工具,可以提高開發(fā)效率,避免手動(dòng)編寫大量的重復(fù)代碼,本文主要介紹了Mybatis創(chuàng)建逆向工程的步驟,感興趣的可以了解一下
    2023-10-10
  • SpringBoot可以同時(shí)處理多少請(qǐng)求流程分析

    SpringBoot可以同時(shí)處理多少請(qǐng)求流程分析

    SpringBoot默認(rèn)的內(nèi)嵌容器是Tomcat,也就是我們的程序?qū)嶋H上是運(yùn)行在Tomcat里的,所以與其說(shuō)SpringBoot可以處理多少請(qǐng)求,到不如說(shuō)Tomcat可以處理多少請(qǐng)求,這篇文章主要介紹了SpringBoot可以同時(shí)處理多少請(qǐng)求,需要的朋友可以參考下
    2023-02-02
  • Mybatis-Plus中的MetaObjectHandler組件的使用

    Mybatis-Plus中的MetaObjectHandler組件的使用

    MetaObjectHandler是Mybatis-Plus中一個(gè)實(shí)用組件,專門用于自動(dòng)處理實(shí)體對(duì)象中的特定字段,如創(chuàng)建時(shí)間、更新時(shí)間、創(chuàng)建人和修改人等,該接口允許開發(fā)者在不修改業(yè)務(wù)代碼的情況下,實(shí)現(xiàn)自動(dòng)填充功能,極大地簡(jiǎn)化了代碼的復(fù)雜性,感興趣的可以了解一下
    2024-10-10
  • Java單鏈表反轉(zhuǎn)圖文教程

    Java單鏈表反轉(zhuǎn)圖文教程

    這篇文章主要給大家介紹了關(guān)于Java單鏈表反轉(zhuǎn)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 關(guān)于Javaweb的轉(zhuǎn)發(fā)和重定向詳解

    關(guān)于Javaweb的轉(zhuǎn)發(fā)和重定向詳解

    這篇文章主要介紹了關(guān)于Javaweb的轉(zhuǎn)發(fā)和重定向詳解,請(qǐng)求的轉(zhuǎn)發(fā),是指服務(wù)器收到請(qǐng)求后,從一個(gè)服務(wù)器端資源跳轉(zhuǎn)到同一個(gè)服務(wù)器端另外一個(gè)資源的操作,需要的朋友可以參考下
    2023-05-05
  • jxls2.4.5如何動(dòng)態(tài)導(dǎo)出excel表頭與數(shù)據(jù)

    jxls2.4.5如何動(dòng)態(tài)導(dǎo)出excel表頭與數(shù)據(jù)

    這篇文章主要介紹了jxls2.4.5如何動(dòng)態(tài)導(dǎo)出excel表頭與數(shù)據(jù)問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • Java8?函數(shù)式編程stream流使用詳解

    Java8?函數(shù)式編程stream流使用詳解

    這篇文章主要介紹了Java8?函數(shù)式編程stream流使用詳解的相關(guān)資料,需要的朋友可以參考下
    2023-07-07
  • 手把手教你如何獲取微信用戶openid

    手把手教你如何獲取微信用戶openid

    眾所周知小程序的openid相當(dāng)重要,它是用戶的唯一標(biāo)識(shí)id,牽扯的支付,登錄,授權(quán)等,下面這篇文章主要給大家介紹了關(guān)于如何獲取微信用戶openid的相關(guān)資料,需要的朋友可以參考下
    2023-02-02

最新評(píng)論