Java集合中的鏈表與結(jié)構(gòu)詳解
前情提要:在學(xué)習(xí) ArrayList 時(shí),認(rèn)識到由于其底層是一段連續(xù)空間,當(dāng)在 ArrayList 任意位置插入或者刪除元素時(shí),就需要將后序元素整體往前或者往后搬移,時(shí)間復(fù)雜度為O(n),效率比較低,因此 ArrayList 不適合做任意位置插入和刪除比較多的場景。因此:java 集合中又引入了LinkedList,即鏈表結(jié)構(gòu)。
一、鏈表概念與結(jié)構(gòu)
鏈表是一種物理存儲結(jié)構(gòu)上非連續(xù)的存儲結(jié)構(gòu),數(shù)據(jù)元素的邏輯順序的通過鏈表中的引用鏈接次序?qū)崿F(xiàn)的。
其結(jié)構(gòu)總共有8種:
帶頭鏈表中的第一個(gè)節(jié)點(diǎn)相當(dāng)于一個(gè)標(biāo)記,如果采用頭插法新增節(jié)點(diǎn),只能在當(dāng)前頭的下一個(gè)節(jié)點(diǎn)插入;而如果是不帶頭的鏈表,頭插法是在第一個(gè)節(jié)點(diǎn)前面新增節(jié)點(diǎn)。

二、當(dāng)向單鏈表的實(shí)現(xiàn)
整個(gè)實(shí)現(xiàn)將圍繞下圖展開:
定義一個(gè) cur 對象,表示當(dāng)前節(jié)點(diǎn)。用法:遍歷鏈表。

注意
1、cur 為空和 cur.next 為空的區(qū)別。
2、單向鏈表不能回退。
2.1 準(zhǔn)備工作
1、先定義一個(gè)類用來表示整個(gè)鏈表,名為 SingleLinkedList。
2、而鏈表中包含節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)帶有兩個(gè)域,一個(gè)是數(shù)據(jù)域存儲整型數(shù)據(jù);另一個(gè)是指針域,指針域中存放的是下一個(gè) 節(jié)點(diǎn) 的引用,因此其類型也就是節(jié)點(diǎn);且注意兩個(gè)屬性都用 public 修飾,在測試時(shí)大有用途。將每個(gè)節(jié)點(diǎn)封裝成鏈表的內(nèi)部類。
3、定義一個(gè)頭部節(jié)點(diǎn),用于查找或者輸出鏈表數(shù)據(jù),但這里并不代表鏈表帶頭。
4、將對鏈表的操作封裝成一個(gè)接口,其功能包括打印鏈表數(shù)據(jù) display、計(jì)算鏈表長度 size、查找數(shù)據(jù) contains、頭插法插入數(shù)據(jù) addFirst、尾插法插入數(shù)據(jù) addLast、任意位置插入數(shù)據(jù) addIndex、刪除第一次出現(xiàn) key 的節(jié)點(diǎn) remove、刪除所有值為 key 的節(jié)點(diǎn) removeAllKey、清空。
SingleLinkedList 鏈表:
package test;
// 不帶頭 單向 鏈表
public class SingleLinkedList implements ILink{
static class ListNode{ // 每一個(gè) 節(jié)點(diǎn) 都是對象,具有共同屬性,因此可以抽象成內(nèi)部類
public int val;
public ListNode next; // 節(jié)點(diǎn)的地址,類型也應(yīng)該是節(jié)點(diǎn)的類型
public ListNode(int val){
this.val = val;
}
}
public ListNode head; // 頭節(jié)點(diǎn)
@Override
// ......
}ILink 接口:
package test;
/**
* 鏈表的操作
*/
public interface ILink {
//頭插法
void addFirst(int data);
//尾插法
void addLast(int data);
//任意位置插入,第一個(gè)數(shù)據(jù)節(jié)點(diǎn)為0號下標(biāo)
void addIndex(int index,int data);
//查找是否包含關(guān)鍵字key是否在單鏈表當(dāng)中
boolean contains(int key);
//刪除第一次出現(xiàn)關(guān)鍵字為key的節(jié)點(diǎn)
void remove(int key);
//刪除所有值為key的節(jié)點(diǎn)
void removeAllKey(int key);
//得到單鏈表的長度
int size();
// 清空
void clear();
// 打印鏈表數(shù)據(jù)
void display();
}在實(shí)現(xiàn)具體的操作之前,還需要考慮鏈表是否為空,即 head == null ?
2.2 初始化鏈表
在具體實(shí)現(xiàn)各項(xiàng)功能之前,需要有一個(gè)原始的鏈表,利于展示操作效果。其定義方法如下
package test;
public class SingleLinkedList implements ILink{
// ......
public void creatList(){ // 創(chuàng)建一個(gè)原始鏈表
ListNode node1 = new ListNode(1);
ListNode node2 = new ListNode(2);
ListNode node3 = new ListNode(3);
ListNode node4 = new ListNode(4);
this.head = node1;
node1.next = node2;
node2.next = node3;
node3.next = node4;
}
// ......
}2.3 打印數(shù)據(jù)、鏈表長度、查找數(shù)據(jù)
這三個(gè)功能都需要將鏈表從頭到尾遍歷一遍。而遍歷的條件只是當(dāng)前節(jié)點(diǎn)不為空。
package test;
public class SingleLinkedList implements ILink{
// ......
@Override
public void display() {
ListNode cur = head;
while(cur != null){
System.out.print(cur.val + " ");
cur = cur.next;
}
System.out.println(); // 換行
}
@Override
public int size() {
ListNode cur = head;
int count = 0;
while (cur != null){
count++;
cur = cur.next;
}
return count;
}
@Override
public boolean contains(int key) {
ListNode cur = head;
while (cur != null){
if(cur.val == key){
return true;
}
cur = cur.next;
}
return false;
}
}package test;
public class TestSingle {
public static void main(String[] args) {
// ILink iLink = new SingleLinkedList(); // 通過接口無法調(diào)用 creatList()
SingleLinkedList linkedList = new SingleLinkedList();
linkedList.creatList(); // 還沒實(shí)現(xiàn)新增節(jié)點(diǎn)功能前調(diào)用的原始鏈表
linkedList.display();
System.out.println(linkedList.size());
}
}2.4 頭插法

@Override
public void addFirst(int data) {
ListNode newNode = new ListNode(data);
newNode.next = head;
this.head = newNode;
}即使原先的鏈表是空的,代碼一樣能實(shí)現(xiàn)頭插法插入節(jié)點(diǎn)。
2.5 尾插法

@Override
public void addLast(int data) {
ListNode newNode = new ListNode(data);
if (head == null){ // 原來鏈表中一個(gè)節(jié)點(diǎn)都沒有的情況下
head = newNode;
return;
}
ListNode cur = head;
while (cur.next != null){
cur = cur.next;
} // 循環(huán)走完說明 cur.next == null 了
cur.next = newNode;
}package test_8_7;
public class TestSingle {
public static void main(String[] args) {
SingleLinkedList linkedList = new SingleLinkedList();
// 實(shí)現(xiàn)新增節(jié)點(diǎn)功能之后,不需要調(diào)用 creatList(),也可以創(chuàng)建鏈表
// 頭插法
linkedList.addFirst(11);
linkedList.addFirst(22);
linkedList.addFirst(33);
linkedList.addFirst(44);
// 尾插法
linkedList.addLast(55);
linkedList.display();
System.out.println(linkedList.size());
}
}2.6 任意位置插入節(jié)點(diǎn)
注意
1、指定位置的合法性;
2、指定下標(biāo)為 0 和 指定位置等于鏈表長度 的情況分開處理;
3、單向鏈表不能回退,因此注意 cur 的位置;
4、所有的插入,優(yōu)先綁定后面的節(jié)點(diǎn)。

@Override
public void addIndex(int index, int data) throws IllegalIndexException{
int len = this.size(); // 存儲當(dāng)前長度,好處:提高效率
if (index < 0 || index > len){
throw new IllegalIndexException("指定位置不合法?。?!");
}else {
if (index == 0){
this.addFirst(data);
return;
}
if (index == len){
this.addLast(data);
return;
}
ListNode newNode = new ListNode(data);
ListNode cur = head;
while (index - 1 != 0){
cur = cur.next;
index--;
}
newNode.next = cur.next;
cur.next = newNode;
}
}package test;
// 處理指定位置的不合法異常
public class IllegalIndexException extends RuntimeException{
public IllegalIndexException(){
}
public IllegalIndexException(String msg){
super(msg);
}
}2.7 刪除第一次出現(xiàn) key 的節(jié)點(diǎn)

@Override
public void remove(int key) {
if (head == null){
return;
}
if(head.val == key){
head = null;
}
ListNode cur = findNodeOfKey(key);
if (cur == null){
return;
}
ListNode del = cur.next;
cur.next = del.next;
}
public ListNode findNodeOfKey(int key){ // 找到存儲的數(shù)據(jù)是key的對象,并返回
ListNode cur = head;
while (cur.next != null){
if (cur.next.val == key){
return cur;
}
cur = cur.next;
}
return null;
}提示
1、在鏈表中查找 key 可封裝成一個(gè)方法
2、查找 key 的條件 cur.next 不為空的前提下,已經(jīng)判斷了 cur.next 存儲的數(shù)據(jù)是否等于 key 了
2.8 刪除鏈表中所有數(shù)據(jù)為 key 的節(jié)點(diǎn)



@Override
public void removeAllKey(int key) {
if (head == null){
return;
}
ListNode prev = head;
ListNode cur = head.next;
while (cur != null){
if (cur.val == key){
prev.next = cur.next;
cur = cur.next;
}else{
prev = cur;
cur = cur.next;
}
}
if (head.val == key){
head = head.next;
}
}2.9 清空
像之前“清空” ArrayList 的方法在鏈表中是不可行的,因?yàn)槿绻靡恢贝嬖?,那么引用所指的對象無法被內(nèi)存回收,容易造成內(nèi)存泄漏,因此只有將 next 都置空了才算清空了鏈表數(shù)據(jù)。

@Override
public void clear() {
ListNode cur = this.head;
while (cur != null){
ListNode prev = cur.next;
cur.next = null;
cur = prev;
}
head = null;
}三、面試題
3.1 刪除鏈表中等于給定值 key 的所有節(jié)點(diǎn)。(與上面的 2.8 一個(gè)意思)
3.2反轉(zhuǎn)一個(gè)單鏈表。

public ListNode reverseList() { // 反轉(zhuǎn)
if(head == null){
return null;
}
ListNode cur = head.next;
head.next = null;
while(cur != null){
ListNode curNode = cur.next;
cur.next = head;
head = cur;
cur = curNode;
}
return head;
}3.3返回鏈表中的中間節(jié)點(diǎn),如果有兩個(gè)中間節(jié)點(diǎn),則返回第2個(gè)節(jié)點(diǎn)。
提示,不能通過計(jì)算鏈表長度的方法進(jìn)行編程。
那么,采用雙指針的方法,快指針走兩步,慢指針走1步,最后慢指針指向的就是中間。

public ListNode middleNode() { // 找中間節(jié)點(diǎn)
ListNode fast = head; // 快指針,走兩步
ListNode slow = head; // 慢指針,走一步
while(fast != null && fast.next != null){ // &&前面必須是 fast != null 的條件
fast = fast.next.next;
slow = slow.next;
}
/*while(fast.next != null && fast != null){ // 輸出 NullPointerException
fast = fast.next.next;
slow = slow.next;
}*/
return slow;
}3.4輸出該鏈表中倒數(shù)第 k 個(gè)節(jié)點(diǎn)。
雖然 leetcode 上已經(jīng)保證了 k 的合法性,但自己實(shí)現(xiàn)的時(shí)候還是需要注意 k 的有效范圍。

public int kthToLast(int k) { // 返回倒數(shù)第k個(gè)字節(jié)的數(shù)據(jù)
if(head == null){
return -1;
}
// 注意k的范圍
if (k <= 0){
return -1;
}
/*if (k > 5){ // 這樣寫還得求鏈表的長度,不好
return -1;
}*/
ListNode fast = head;
ListNode slow = head;
int count = 0;
while(count != k-1){ // 為了與慢指針拉開一定的距離
fast = fast.next;
if(fast == null) // 這里就是判斷k是否超出鏈表長度的條件
return -1;
count++;
}
while(fast.next != null){
fast = fast.next;
slow = slow.next;
}
return slow.val;
}3.5合并兩個(gè)有序鏈表并按升序排序成有序鏈表返回。
提示
1、創(chuàng)建一個(gè)頭節(jié)點(diǎn),作為標(biāo)志,可存儲數(shù)據(jù),但該數(shù)據(jù)無實(shí)際意義;
2、返回的節(jié)點(diǎn)不是創(chuàng)建的頭節(jié)點(diǎn)。
3、在自己實(shí)現(xiàn)的鏈表中實(shí)現(xiàn)時(shí),需要注意,因?yàn)樵摲椒ú僮鞯氖莾蓚€(gè)鏈表,因此不好將它定義到 SingleLinkedList 這個(gè)類中,因此直接定義到測試類。但直接定義到測試類時(shí)因?yàn)?ListNode 是 SingleLinkedList 的內(nèi)部類,需要用 SingleLinkedList. 來調(diào)用 ListNode

package test;
public class TestSingle {
public static SingleLinkedList.ListNode mergeTwoLists
(SingleLinkedList.ListNode headA, SingleLinkedList.ListNode headB) { // 合并兩個(gè)有序鏈表并排序
SingleLinkedList.ListNode newHead = new SingleLinkedList.ListNode(-1); // 隨便傳一個(gè)數(shù)據(jù),因?yàn)檫@個(gè)數(shù)據(jù)無效
SingleLinkedList.ListNode tmp = newHead;
while(headA != null && headB != null){
if (headA.val < headB.val){
tmp.next = headA;
headA = headA.next;
tmp = tmp.next;
}else{
tmp.next = headB;
headB = headB.next;
tmp = tmp.next;
}
}
if (headA != null){
tmp.next = headA;
}
if (headB != null){
tmp.next = headB;
}
return newHead.next;
}
public static void main(String[] args) {
// 測試合并兩個(gè)鏈表
SingleLinkedList linkedList = new SingleLinkedList();
linkedList.addFirst(4);
linkedList.addLast(11);
linkedList.addLast(19);
linkedList.addLast(44);
SingleLinkedList linkedList2 = new SingleLinkedList();
linkedList2.addFirst(3);
linkedList2.addLast(6);
linkedList2.addLast(32);
linkedList2.addLast(57);
SingleLinkedList.ListNode newNode = mergeTwoLists(linkedList.head, linkedList2.head);
linkedList.display(newNode);
}
}3.6以 x 值為基準(zhǔn)將鏈表分割成兩部分,所有小于 x 的節(jié)點(diǎn)排在大于或等于 x 的節(jié)點(diǎn)之后。

public ListNode partition(int x) { // 不改變原來數(shù)據(jù)的順序下,將所有小于x的結(jié)點(diǎn)排在其余結(jié)點(diǎn)之前
ListNode beforeStart = null; // 小于x的頭節(jié)點(diǎn)
ListNode beforeEnd = null; // 小于x的尾節(jié)點(diǎn)
ListNode afterStart = null; // 大于x的頭節(jié)點(diǎn)
ListNode afterEnd = null; // 大于x的尾節(jié)點(diǎn)
ListNode cur = head;
while(cur != null){
if(cur.val < x){
if(beforeStart == null){ // 第一次插入
beforeStart = beforeEnd = cur;
}else{
beforeEnd.next = cur;
beforeEnd = beforeEnd.next;
}
}else{
if(afterStart == null){
afterStart = afterEnd = cur;
}else{
afterEnd.next = cur;
afterEnd = afterEnd.next;
}
}
cur = cur.next;
}
// 如果沒有小于x的節(jié)點(diǎn)
if (beforeStart == null){
return afterStart;
}
// 前后兩部分銜接起來
beforeEnd.next = afterStart;
// 第2部分的最后一個(gè)節(jié)點(diǎn)的引用要置空,否則編譯超出范圍
if(afterStart != null){
afterEnd.next = null;
}
return beforeStart;
}3.7判斷是否為回文鏈表。
提示
1、找到鏈表的中間節(jié)點(diǎn);
2、將中間節(jié)點(diǎn)后面的節(jié)點(diǎn)反轉(zhuǎn);
3、頭節(jié)點(diǎn)的值與最后一個(gè)節(jié)點(diǎn)的值進(jìn)行比較,然后頭節(jié)點(diǎn)往后,最后一個(gè)節(jié)點(diǎn)往前。
注意此題需要區(qū)分鏈表的節(jié)點(diǎn)數(shù),如果是奇數(shù)比較好判斷,但如果是偶數(shù),需要考慮另一個(gè)判斷條件。
奇數(shù)情況下:

偶數(shù)情況下:

判斷條件是 fast.next = slow; 不能是 slow.next = fast;
且該判斷條件前提是兩者的數(shù)據(jù)是相等的,因此判斷順序很重要。
public boolean chkPalindrome(){ // 判斷是否是回文鏈表
if(head == null){
return true;
}
// 1、找到中間節(jié)點(diǎn)
ListNode fast = head;
ListNode slow = head;
while(fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
}
// 2、反轉(zhuǎn)
ListNode cur = slow.next;
while(cur != null){
ListNode curN = cur.next;
cur.next = slow;
slow = cur;
cur = curN;
}
// 3、判斷是否是回文
while(head != slow){
if (head.val != slow.val){
return false;
}
// 如果鏈表是偶數(shù)的話,應(yīng)該是下面的判斷條件
// 前提是兩個(gè)val值是相等的
if (head.next == slow){ // 注意是head的下一個(gè)節(jié)點(diǎn)是slow才對,因?yàn)閟low的下一個(gè)節(jié)點(diǎn)回到了slow后面了。
return true;
}
head = head.next;
slow = slow.next;
}
return true;
}3.8輸入兩個(gè)鏈表,找出它們的公共節(jié)點(diǎn)。

public SingleLinkedList.ListNode getIntersectionNode
(SingleLinkedList.ListNode headA, SingleLinkedList.ListNode headB) { // 兩鏈表是否相交
SingleLinkedList.ListNode pLong = headA; // 假設(shè)鏈表A的長度比鏈表B的長
SingleLinkedList.ListNode pShort = headB;
int lenA = 0; // 鏈表A的長度
int lenB = 0; // 鏈表B的長度
while (pLong != null){
lenA++;
pLong = pLong.next;
}
while (pShort != null){
lenB++;
pShort = pShort.next;
}
// 因?yàn)樵谟?jì)算長度時(shí)改變了兩個(gè)值,因此要從新定義
pLong = headA;
pShort = headB;
// 計(jì)算兩個(gè)鏈表長度的差值
int len = lenA - lenB;
if (len < 0){ // 如果len為負(fù)數(shù),說明lenB大于lenA,規(guī)定pLong一定指向長的鏈表
pLong = headB;
pShort = headA;
len = lenB - lenA; // 記住要把差值換成正數(shù)
}
// 長的鏈表先走len步
while (len != 0){
pLong = pLong.next;
len--;
}
// 兩個(gè)引用同時(shí)走,知道它們相遇
while (pLong != pShort){
pLong = pLong.next;
pShort = pShort.next;
}
if (pLong == null){
return null; // 說明沒有相交
}
return pLong;
}測試:
public static void creatIntersect
(SingleLinkedList.ListNode headA, SingleLinkedList.ListNode headB){ // 自己實(shí)現(xiàn)相交
headA.next.next = headB.next.next.next;
}
public static void main(String[] args) {
SingleLinkedList linkedList = new SingleLinkedList();
linkedList.addFirst(5);
linkedList.addLast(1);
linkedList.addLast(8);
linkedList.addLast(4);
linkedList.addLast(5);
SingleLinkedList linkedList2 = new SingleLinkedList();
linkedList2.addFirst(4);
linkedList2.addLast(1);
linkedList2.addLast(6);
linkedList2.addLast(8);
linkedList2.addLast(4);
linkedList2.addLast(5);
creatIntersect(linkedList.head, linkedList2.head);
SingleLinkedList.ListNode ret = getIntersectionNode(linkedList.head, linkedList2.head);
System.out.println(ret.val);
}3.9判斷鏈表中是否有環(huán)。* 進(jìn)階:給定一個(gè)鏈表的頭節(jié)點(diǎn) head ,返回鏈表開始入環(huán)的第一個(gè)節(jié)點(diǎn)。 如果鏈表無環(huán),則返回 null。


public boolean hasCycle(){ // 判斷當(dāng)前鏈表是否有環(huán)
if (head == null){
return false;
}
ListNode fast = head;
ListNode slow = head;
while (fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if (fast == slow){
return true;
}
}
return false;
}
public void creatLoop(){ // 創(chuàng)建環(huán)
ListNode cur = head;
while (cur.next != null){
cur = cur.next;
}
cur.next = head.next.next.next;
}
public ListNode detectCycle() { // 給定一個(gè)鏈表,返回鏈表開始入環(huán)的第一個(gè)節(jié)點(diǎn)。 如果鏈表無環(huán),則返回 NULL
ListNode fast = head;
ListNode slow = head;
while( fast != null && fast.next != null){
fast = fast.next.next;
slow = slow.next;
if(fast == slow){
break;
}
}
if(fast == null || fast.next == null){
return null; // 說明沒有環(huán)
}
slow = head;
while(fast != slow){
fast = fast.next;
slow = slow.next;
}
return slow;
}測試類:
public class TestSingle {
public static void main(String[] args) {
// 測試返回鏈表開始入環(huán)的第一個(gè)節(jié)點(diǎn)。
SingleLinkedList linkedList = new SingleLinkedList();
linkedList.addFirst(5);
linkedList.addLast(1);
linkedList.addLast(8);
linkedList.addLast(4);
linkedList.addLast(5);
linkedList.creatLoop();
System.out.println(linkedList.hasCycle());
SingleLinkedList.ListNode ret = linkedList.detectCycle();
System.out.println(ret.val);
}
}到此這篇關(guān)于Java集合中的鏈表與結(jié)構(gòu)詳解的文章就介紹到這了,更多相關(guān)java集合鏈表內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
解析電子郵件的基本概念及JavaMail API郵件功能使用
這篇文章主要介紹了電子郵件的基本概念及JavaMail API郵件功能使用,包括用Java來發(fā)送郵件的示例,需要的朋友可以參考下2016-02-02
Java如何實(shí)現(xiàn)海量數(shù)據(jù)判重
在海量數(shù)據(jù)如何確定一個(gè)值是否存在?這是一道非常經(jīng)典的面試場景題,那怎么回答這個(gè)問題呢?下面小編就來和大家詳細(xì)的聊一聊,感興趣的可以一起學(xué)習(xí)一下2023-09-09
Java編程實(shí)現(xiàn)用hash方法切割文件
這篇文章主要介紹了Java編程實(shí)現(xiàn)用hash方法切割文件,簡單介紹了hash的概念,然后分享了使用方法示例,具有一定借鑒價(jià)值,需要的朋友可以了解下。2017-12-12
Spring boot如何通過@Scheduled實(shí)現(xiàn)定時(shí)任務(wù)及多線程配置
這篇文章主要介紹了Spring boot如何通過@Scheduled實(shí)現(xiàn)定時(shí)任務(wù)及多線程配置,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
Spring Boot環(huán)境下Mybatis Plus的快速應(yīng)用操作
這篇文章主要介紹了Spring Boot環(huán)境下Mybatis Plus的快速應(yīng)用操作,具有很好的價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-11-11
基于spring-boot-maven-plugin插件打包lib文件外置的方法(layout模式為ZIP模式)
Maven是一個(gè)插件執(zhí)行框架,所有工作都由插件完成,同時(shí)?Maven?基于構(gòu)建生命周期的核心概念,明確定義了構(gòu)建和分發(fā)特定工件(項(xiàng)目)的過程,接下來通過本文給大家介紹下基于spring-boot-maven-plugin插件打包lib文件外置(layout模式為ZIP模式),需要的朋友可以參考下2022-09-09
Spring Boot 整合 Druid 并開啟監(jiān)控的操作方法
本文介紹了如何在SpringBoot項(xiàng)目中引入和配置Druid數(shù)據(jù)庫連接池,并開啟其監(jiān)控功能,通過添加依賴、配置數(shù)據(jù)源、開啟監(jiān)控、自定義配置以及訪問監(jiān)控頁面,開發(fā)者可以有效提高數(shù)據(jù)庫訪問效率并監(jiān)控連接池狀態(tài),感興趣的朋友跟隨小編一起看看吧2025-01-01
SpringMVC框架和SpringBoot項(xiàng)目中控制器的響應(yīng)結(jié)果深入分析
這篇文章主要介紹了SpringMVC框架和SpringBoot項(xiàng)目中控制器的響應(yīng)結(jié)果,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧2022-12-12

