數據結構預備知識

在學習數據結構之前,有些知識是很有必要提前知道的,它們包括:集合框架、復雜度和泛型。本篇文章專門介紹這三個東西。

1.集合框架

1.1 什么是集合框架

Java 集合框架(Java Collection Framework),又被稱為容器,是定義在 java.util 包下的一組接口 和 其實現類。其主要表現為將多個元素置于一個單元中,用與對這些元素進行快速、便捷的存儲、檢索、管理,即我們平時俗稱的增刪查改

以下是Java集合框架的完整體系圖,梳理了集合框架中比較重要的接口、抽象類與具體的類的繼承/實現關系。

?1.2 集合框架的重要性

  1. 使用成熟的集合框架,有助于我們便捷、快速的寫出高效、穩定的代碼。
  2. 學習背后的數據結構知識,有助于我們理解各個集合的優缺點及使用場景。

?1.3 數據結構以及算法

1.3.1 什么是數據結構

數據結構(Data Structure)是計算機存儲、組織數據的方式,指相互之間存在一種或多種特定關系的數據元素的集合。

關于數據結構的一些問答:

1.Java的數據結構與C語言的數據結構有區別嗎?

“沒有”區別,只不過是實現的語言不一樣。

2.數據結構和數據庫是一個東西嗎?

有區別的,數據庫其實是用來儲存數據的,數據庫在儲存數據的時候,底層會用到數據結構。

3.數據結構怎么樣才能學好?

多思考,多畫圖,多寫代碼,多去調試。

1.3.2 什么是算法

算法(Algorithm):就是定義良好的計算過程,他取一個或一組的值為輸入,并產生出一個或一組值作為輸出。簡單來說算法就是一系列的計算步驟,用來將輸入數據轉化成輸出結果。

如何學好算法呢?

死磕代碼,注意畫圖和思考,多寫博客總結和多刷題。

另外,數據結構與算法相輔相成

2.復雜度

知道了什么是算法,那么如何去衡量一個算法的好壞呢?這就引出了新概念——算法效率

2.1 算法效率

算法效率分析分為兩種:第一種是時間效率,第二種是空間效率。時間效率被稱為時間復雜度,而空間效率被稱作空間復雜度。 時間復雜度主要衡量的是一個算法的運行速度,而空間復雜度主要衡量一個算法所需要的額外空間,在計算機發展的早期,計算機的存儲容量很小。所以對空間復雜度很是在乎。但是經過計算機行業的迅速發展,計算機的存儲容量已經達到了很高的程度。所以我們如今已經不需要再特別關注一個算法的空間復雜度。

2.2 時間復雜度

2.2.1 時間復雜度的概念

時間復雜度的定義:在計算機科學中,算法的時間復雜度是一個數學函數,它定量描述了該算法的運行時間。一個 算法執行所耗費的時間,從理論上說,是不能算出來的,只有你把你的程序放在機器上跑起來,才能知道。但是我們需要每個算法都上機測試嗎?是可以都上機測試,但是這很麻煩,所以才有了時間復雜度這個分析方式。一個算法所花費的時間與其中語句的執行次數成正比例,算法中的基本操作的執行次數,為算法的時間復雜度

可以舉個例子,現有一函數:

public void func(int N) {int count = 0;for (int i = 0; i < N; i++) {for (int j = 0; j < N; j++) {count++;}}for (int i = 0; i < 2*N; i++) {count++;}int m = 10;while ((m--) > 0) {count++;}System.out.println(count);}

結合時間復雜度的概念及這個函數,可以得出 func執行的基本操作次數為:

F(N) = N^2 + 2*N + 10

2.2.2? 大o的漸進表示法

實際中我們計算時間復雜度時,我們其實并不一定要計算精確的執行次數,而只需要大概執行次數,那么這里我們使用大O的漸進表示法。

大O符號(Big O notation):是用于描述函數漸進行為的數學符號。

大o的漸進表示法的規則

  1. 用常數1取代運行時間中的所有加法常數。
  2. 在修改后的運行次數函數中,只保留最高階項。
  3. 如果最高階項存在且不是1,則去除與這個項目相乘的常數。得到的結果就是大O階。

那么使用大o的漸進表示法,上述函數 func 的時間復雜度為:

O(N^2)

大o的漸進表示法去掉了那些對結果影響不大的項,簡潔明了的表示出了執行次數

另外,算法的時間復雜度還存在著最好、平均和最壞情況:

最好情況:任意輸入規模的最小運行次數(下界)。

平均情況:所有可能的輸入下,算法執行所需時間的平均度量。

最壞情況:任意輸入規模的最大運行次數(上界)

在實際中一般情況下,關注的是算法的最壞運行情況

2.2.3?常見的時間復雜度計算舉例

1.冒泡排序

void bubbleSort(int[] array) {for (int end = array.length; end > 0; end--) {boolean sorted = true;for (int i = 1; i < end; i++) {if (array[i - 1] > array[i]) {Swap(array, i - 1, i);sorted = false;}}if (sorted == true) {break;}}}

這個方法基本操作在最好情況下會執行N次,即一開始這個這個數組就已經排好序了,最壞情況下:數組完全逆序排列,那么第一輪需要操作 n-1次,第二輪需要操作 n-2次,第三輪需要操作 n-3次,……,最后一輪需要操作 1次,那么合起來就是:(n-1) + (n-2) + …… + 1 = (n-1)*n/2,用大o漸進表示法,得:O(N^2)。

2.二分查找

int binarySearch(int[] array, int value) {int begin = 0;int end = array.length - 1;while (begin <= end) {int mid = begin + ((end-begin) / 2);if (array[mid] < value)begin = mid + 1;else if (array[mid] > value)end = mid - 1;elsereturn mid;}return -1;}

這個方法的基本操作在最好情況下執行1次,即目標值剛好在中間,最壞情況:一直找,直到不滿足循環條件。因為每一輪查找都會使循環區間減半,即令初始區間長度為n,第一輪之后,區間長度變為 n/2,第二輪之后,n/4,……,第k輪后,n/(2*k),此時需要繼續縮小區間,直到區間為0,即?n/(2*k) <= 1,那么有 k 約等于 n以2為底的對數,使用大o的漸進表示法,得:O(n以2為底的對數)。

3.一般遞歸

long factorial(int N) {return N < 2 ? N : factorial(N-1) * N;}

像這種一般遞歸的方法, 通常它的時間復雜度 = 遞歸的次數 * 每次遞歸執行的次數。像這個方法,它的時間復雜度 = (N - 1)* 1 = N - 1,使用大o的漸進表示法,得:O(N)。

4.斐波那契數列的遞歸

int fibonacci(int N) {return N < 2 ? N : fibonacci(N-1)+fibonacci(N-2);}

?用遞歸求斐波那契數列的方法不能看出一般的遞歸方法,因為當它在計算 fibonacci(N)時,這個方法又會調用 fibonacci(N - 1)和 fibonacci(N-2),這兩個子問題又會各自調用更小規模的子問題,形成一個類似二叉樹的調用結構:

使用大o的漸進表示法,得:O(2^n)。

?2.3 空間復雜度

空間復雜度是對一個算法在運行過程中臨時占用存儲空間大小的量度 。空間復雜度衡量的是算法在執行過程中額外占用的存儲空間(不包括輸入數據本身占用的空間)。空間復雜度不是程序占用了多少bytes的空間,因為這個也沒太大意義,所以空間復雜度算的是變量的個數。空間復雜度計算規則基本跟時間復雜度類似,也使用大O漸進表示法

舉個例子:

void bubbleSort(int[] array) {for (int end = array.length; end > 0; end--) {boolean sorted = true;for (int i = 1; i < end; i++) {if (array[i - 1] > array[i]) {Swap(array, i - 1, i);sorted = false;}}if (sorted == true) {break;}}}

這個冒泡排序方法中僅使用了幾個固定的變量:end、sorted、i ,這些變量的占用的存儲空間不會隨著輸入數組的大小變化而變化,交換元素的 Swap方法也只需要臨時變量來交換兩個元素,同樣不依賴與數組規模。因此它的空間復雜度為3,使用大o的漸進表示法,得:O(1)。

3.泛型

3.1 包裝類

在Java中,由于基本數據類型不是繼承自Object,為了在泛型代碼中可以支持基本類型,Java給每個基本類型都對應了一個包裝類型。

3.1.1 裝箱與拆箱

?裝箱(也叫裝包):把基本數據類型 變為 包裝類類型的過程叫做裝箱。

拆箱(也叫拆包):把保證類類型 變為 基本數據類型的過程叫做拆箱。

?int i = 10;

//裝箱操作,新建一個 Integer 類型對象,將 i 的值放入對象的某個屬性中

Integer i1 = Integer.valueOf(i);

Integer i2?= new Integer(i);

//拆箱操作,將 Integer 對象中的值取出,放到一個基本數據類型中

int j = i1.intValue();

3.1.2 自動裝箱與自動拆箱

?裝箱和拆箱分為自動和顯式,上述就是顯式裝箱和顯式拆箱。從顯示裝箱和顯式拆箱的使用過程來看,它們的操作帶來了不少的代碼量,所以為了減少開發者的負擔,Java提供了自動機制:

?int i = 10;

//自動裝箱

Integer i1 = i;

Integer i2?= (Integer)i;

//自動拆箱

int j = i1;

int k = (int)i1;

那么自動裝箱和自動拆箱的底層機制到底是怎么樣的呢?很簡單,底層是在我們使用自動裝箱和自動拆箱時,Java幫我們調用了具體的方法,也就是使用了顯式的方式。

?3.1.3 裝箱與拆箱的面試題

為什么下列的代碼的輸出結果不一樣?

public class Main {public static void main(String[] args) {Integer a = 100;Integer b = 100;System.out.println(a == b);Integer c = 200;Integer d = 200;System.out.println(c == d);}
}//運行結果
true
false

顯然這里涉及到了裝箱操作,我們都知道裝箱底層上是調用了 Integer.valueOf()方法,那么到Integer類中去找這個方法:

發現:當傳入的 i 在某個范圍內時,是從一個數組中直接去獲取值,當 i 在這個范圍內時,它返回一個新的 Integer對象。但是這個范圍是多少呢?繼續深挖,我們發現:

?low = -128,high = 127,因此得出結論:這個范圍是-128 到 127!這就解釋清楚了,因為傳入a和b的值為100,在這個范圍內,因此它們是從同一個數組內獲取的值,而傳入c和d的值為200,不在這個范圍內,因此它們的值分別來自新建的兩個Integer對象,用 == 進行比較,比較的是它們的地址,a和b來自同一個數組,因此地址相同,故輸出為true,而c和d是兩個不同的對象,因此地址不同,故輸出false。

?3.2 什么是泛型

一般的類和方法,只能使用具體的類型: 要么是基本類型,要么是自定義的類。如果要編寫可以應用于多種類型的代碼,這種刻板的限制對代碼的束縛就會很大,但泛型的出現打破了這種束縛。通俗講,泛型就是適用于許多類型。從代碼上講,就是對類型實現了參數化。

3.3 不使用泛型的問題

現在,要做一件事:實現一個類,類中包含一個數組成員,使得數組中可以存放如何類型的數據,也可以根據成員方法返回數組中某個下標的值。要解決這個問題,我們會想到:

  1. 以前學的數組,只能放指定類型的元素。
  2. 所有類的父類默認為Object類。

那么突發奇想——數組的類型能不能是Object類。


class MyArrays {public Object[] arrays = new Object[10];public void setArrays(int pop,Object obj) {this.arrays[pop] = obj;}public Object getArrays(int pop) {return this.arrays[pop];}
}public class Main {public static void main(String[] args) {MyArrays myArrays = new MyArrays();myArrays.setArrays(0,10);myArrays.setArrays(1,"10");//String str = myArrays.getArrays(2);  //編譯報錯String str = (String) myArrays.getArrays(1);System.out.println(str);}
}

把代碼實現后我們發現:

  1. 任何的類型的數據都可以存放。
  2. 1號下標本身就是字符串,但是直接取出來會報錯,要強制類型轉換才不報錯。

雖然說,在這種情況下什么類型的數據都能放入數組中,但是我們還是希望它只能裝一種數據類型,而不是同時裝這么多類型。而泛型的主要目的就在這里了!就是指定當前的容器,只能裝什么類型的對象,讓編譯器去做檢測。?從而實現:想裝什么類型,就將什么類型作為參數傳入

3.4 泛型的語法

//第一種語法格式

class 分析類名稱 <類型形參列表> {

? ? ? ? //這里可以使用類型參數

}

例如

class ClassName <T1,T2, .... ,Tn> {

}

//第二種語法格式

class 分析類名稱 <類型形參列表> extends 繼承的類 /* 這里可以使用類型參數*/?{

? ? ? ? //這里可以使用類型參數

}

例如

class ClassName <T1,T2, .... ,Tn> extends?ParentClass<T1> {

? ? ? ? //這里可以使用類型參數

}

借助泛型,原來的代碼我們可以改成這樣:

class MyArrays <T>{public Object[] arrays = new Object[10];public void setArrays(int pop,T obj) {this.arrays[pop] = obj;}public T getArrays(int pop) {return (T)this.arrays[pop];}
}
public class Main {public static void main(String[] args) {MyArrays<String> arrays= new MyArrays<>();arrays.setArrays(0,"1");arrays.setArrays(1,"hello");String str = arrays.getArrays(1);System.out.println(str);}
}//運行結果
hello

完全符合我們的預期!

【注意】

  1. 類名之后的<T>代表占位符,表示當前類是一個泛型類
  2. 在main方法中,類型后面加入<String> 表示指定當前類型
  3. 用能夠接收數組元素的變量去接收數組元素不報錯,不需要強制類型轉換
  4. 當存放的元素與泛型類指定的元素不同時,會報錯,編譯器會在存放元素時幫助我們進行類型檢測

?3.5 泛型類的使用

使用的語法格式:

泛型類<類型參數> 變量名;? //定義一個泛型類引用

new 泛型類<類型參數>(構造方法實參);? //實例化一個泛型類對象

舉例

MyArray<Integer> list = new MyArrays<Integer>();

注意:泛型的類型實參只接受類,所有的基本數據類型必須使用包裝類!

類型推導

當編譯器可以可以根據上下文推導出類型實參時,可以省略類型實參的填寫,例如:

MyArray<Integer> list = new MyArrays< >();

?3.6 裸類型

裸類型是一個泛型類但沒有帶著類型實參,例如:

MyArray list = new MyArrays();

//這就是一個裸類型

?注意:我們不要自己去使用裸類型,因為裸類型是為了兼容老版本的 API 保留的機制。

3.7 泛型如何編譯

Java的泛型機制是在編譯時實現的(它的兩個功能:自動類型檢查和自動類型轉換),在編譯的過程中,編譯器會將所有的?T 替換為 T的上界類型,也就是說編譯結束后所有的 T 都被替換為了T的上界類型,這種機制稱為:擦除機制

若沒有 T 沒有指定上界類型,那么默認指定Object類。

3.8 泛型的上界

在定義泛型類時,有時候需要對傳入的類型變量做一定的約束,可以通過類型邊界來約束。

具體的語法格式

class 泛型類名稱<類型形參 extends 類型邊界>? {

? ? ? ? ……

}

舉例:

public class MyArrays<E extends Number> {

? ? ? ? ……

}

//意思是:只接受 Number 的子類型作為 E 的類型實參

注意:沒有指定類型邊界 E,可以視為 E extends Object

特殊場景

public class MyArrays<E extends Comparable<E>> {

? ? ? ? ……

}

//意思是:接收的 E 必須實現了Comparable接口,即extends后面加接口說明傳入的類型實參必須實現這個接口!

3.9 泛型方法

除了有泛型類,還有泛型方法,它的語法格式為:

方法限定符 <類型形參列表> 返回值類型 方法名稱(形參列表) {

? ? ? ? ……

}?

舉例:

class Alg {public <E> void Swap(E[] arrays,int i,int j) {E t = arrays[i];arrays[i] = arrays[j];arrays[j] = t;}
}

?這是一個非靜態的泛型方法,當然也有靜態的泛型方法,即在public后面加 static即可。

關于泛型方法的使用一般有兩種:使用類型推導不使用類型推導。這里拿非靜態的泛型方法舉例:

使用類型推導:

import java.util.Arrays;class Alg {public <E> void Swap(E[] arrays,int i,int j) {E t = arrays[i];arrays[i] = arrays[j];arrays[j] = t;}
}public class Main {public static void main(String[] args) {Integer[] arrays = {1,2,4,3};Alg alg = new Alg();alg.Swap(arrays,2,3);System.out.println(Arrays.toString(arrays));}
}//運行結果
[1, 2, 3, 4]

不使用類型推導:

import java.util.Arrays;class Alg {public <E> void Swap(E[] arrays,int i,int j) {E t = arrays[i];arrays[i] = arrays[j];arrays[j] = t;}
}public class Main {public static void main(String[] args) {Integer[] arrays = {1,2,4,3};Alg alg = new Alg();alg.<Integer>Swap(arrays,2,3);System.out.println(Arrays.toString(arrays));}
}//運行結果
[1, 2, 3, 4]

到此,數據結構的預備知識已經完結!感謝您的閱讀,如有錯誤還請指出!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/916447.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/916447.shtml
英文地址,請注明出處:http://en.pswp.cn/news/916447.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【C++】數字cmath庫常用函數

菜鳥傳送門&#xff1a;https://www.runoob.com/cplusplus/cpp-numbers.html 作者廢話&#xff1a;作為一個從業3年的JS人&#xff0c;現在重拾C&#xff0c;雖然眾多語言都有很多相似之處&#xff08;至少算法&#xff0c;數學運算&#xff0c;數據結構等等那些都是相同的&…

神經網絡(第二課第一周)

文章目錄神經網絡&#xff08;第二課第一周&#xff09;&#xff08;一&#xff09;神經網絡的內涵&#xff08;二&#xff09;如何構建神經元層1、tensorflow如何處理數據&#xff08;Tensorflow 是由 Google 開發的機器學習包。&#xff09;2、詳細的一些實驗代碼&#xff0c…

CCF-GESP 等級考試 2025年6月認證C++七級真題解析

1 單選題&#xff08;每題 2 分&#xff0c;共 30 分&#xff09;第1題 已知小寫字母 b 的ASCII碼為98&#xff0c;下列C代碼的輸出結果是&#xff08; &#xff09;。#include <iostream>using namespace std;int main() { char a b ^ 4; cout << a; …

【HarmonyOS】鴻蒙應用開發中常用的三方庫介紹和使用示例

【HarmonyOS】鴻蒙應用開發中常用的三方庫介紹和使用示例 截止到2025年&#xff0c;目前參考官方文檔&#xff1a;訪問 HarmonyOS三方庫中心 。梳理了以下熱門下載量和常用的三方庫。 上述庫的組合&#xff0c;可快速實現網絡請求、UI搭建、狀態管理等核心功能&#xff0c;顯著…

SpringBoot 獲取請求參數的常用注解

SpringBoot 提供了多種注解來方便地從 HTTP 請求中獲取參數以下是主要的注解及其用法&#xff1a;1. RequestParam用于獲取查詢參數(URL 參數)&#xff0c;適用于 GET 請求或 POST 表單提交。GetMapping("/user") public String getUser(RequestParam("id"…

【Linux篇章】Socket 套接字,竟讓 UDP 網絡通信如此絲滑,成為一招致勝的秘籍!

本篇文章將帶大家了解網絡通信是如何進行的&#xff08;如包括網絡字節序&#xff0c;端口號&#xff0c;協議等&#xff09; &#xff1b;再對socket套接字進行介紹&#xff1b;以及一些udp-socket相關網絡通信接口的介紹及使用&#xff1b;最后進行對基于udp的網絡通信&#…

GIF圖像格式

你可能已經知道&#xff0c;GIF 是一種光柵圖像文件格式&#xff0c;它在不損失圖像質量的前提下提供壓縮功能&#xff0c;并且支持動畫和透明度。 GIF 是“Graphics Interchange Format&#xff08;圖形交換格式&#xff09;”的縮寫。由于其良好的兼容性以及在不同應用程序和…

D3.js的力導向圖使用入門筆記

D3.js是一個用于數據可視化的JavaScript庫,廣泛應用于Web端的數據交互式圖形展示 中文文檔&#xff1a;入門 | D3 中文網 一、D3.js核心特點 1、核心思想 將數據綁定到DOM元素&#xff0c;通過數據動態生成/修改可視化圖形。 2、應用場景 交互式圖表&#xff1a;如動態條…

Zookeeper的分布式事務與原子性:深入解析與實踐指南

引言在分布式系統架構中&#xff0c;事務管理和原子性保證一直是極具挑戰性的核心問題。作為分布式協調服務的標桿&#xff0c;Apache Zookeeper提供了一套獨特而強大的機制來處理分布式環境下的原子操作。本文將深入探討Zookeeper如何實現分布式事務的原子性保證&#xff0c;分…

Lua(迭代器)

Lua 迭代器基礎概念Lua 迭代器是一種允許遍歷集合&#xff08;如數組、表&#xff09;元素的機制。迭代器通常由兩個部分組成&#xff1a;迭代函數和狀態控制變量。每次調用迭代函數會返回集合中的下一個元素。泛型 for 循環Lua 提供了泛型 for 循環來簡化迭代器的使用。語法如…

發布 VS Code 擴展的流程:以顏色主題為例

發布 VS Code 擴展的流程&#xff1a;以顏色主題為例 引言&#xff1a;您的 VS Code 擴展在市場中的旅程 Visual Studio Code (VS Code) 的強大擴展性是其廣受歡迎的核心原因之一&#xff0c;它允許開發者通過添加語言支持、調試器和各種開發工具來定制和增強其集成開發環境&…

C++ 多線程(一)

C 多線程&#xff08;一&#xff09;1.std中的thread API 介紹開啟一個線程獲取線程信息API交換兩個線程2.向線程里傳遞參數的方法第一種方式&#xff08;在創建線程的構造函數后攜帶參數&#xff09;第二種方式&#xff08;Lambda&#xff09;第三種方式&#xff08;成員函數&…

自動駕駛訓練-tub詳解

在 Donkeycar 的環境里&#xff0c;“tub” 是一個很關鍵的術語&#xff0c;它代表的是存儲訓練數據的目錄。這些數據主要來源于自動駕駛模型訓練期間收集的圖像和控制指令。 Tub 的構成 一個標準的 tub 目錄包含以下兩類文件&#xff1a; JSON 記錄文件&#xff1a;其命名格式…

CVPR多模態破題密鑰:跨模對齊,信息串供

關注gongzhonghao【CVPR頂會精選】當今數字化時代&#xff0c;多模態技術正迅速改變我們與信息互動的方式。多模態被定義為在特定語境中多種符號資源的共存與協同。這種技術通過整合不同模態的數據&#xff0c;如文本、圖像、音頻等&#xff0c;為用戶提供更豐富、更自然的交互…

小米路由器3G R3G 刷入Breed和OpenWrt 插入可共享網絡的usb隨身WiFi

小米 R3G 參數&#xff08;以下加黑加粗需要特別關注&#xff0c;灰常詳細&#xff09; 市面上有R3G和R3Gv2兩種型號, 注意區分, 后者是縮水版, 沒有USB口. 內存只有128M, Flash只有16M. 這里描述的只適用于R3G. 就是這樣 操作步驟開始&#xff0c;&#xff0c;注&#xff1a…

SpringBoot實現Serverless:手擼一個本地函數計算引擎

前言 最近突然冒出一個想法&#xff1a;能不能用SpringBoot自己實現一個類似AWS Lambda或阿里云函數計算的執行引擎&#xff1f; 說干就干&#xff0c;于是從零開始設計了一套基于SpringBoot的Serverless執行框架。 這套框架支持函數動態加載、按需執行、資源隔離&#xff0c;甚…

Java排序算法之<插入排序>

目錄 1、插入排序 2、流程介紹 3、java實現 4、性能介紹 前言 在 Java 中&#xff0c; 冒泡排序&#xff08;Bubble Sort&#xff09; 和 選擇排序&#xff08;Selection Sort&#xff09; 之后&#xff0c;下一個性能更好的排序算法通常是 插入排序&#xff08;Insertion …

《計算機網絡》實驗報告七 HTTP協議分析與測量

目 錄 1、實驗目的 2、實驗環境 3、實驗內容 4、實驗結果與分析 4.1 使用tcpdump命令抓包 4.2 HTTP字段分析 5、實驗小結 5.1 問題與解決辦法&#xff1a; 5.2 心得體會&#xff1a; 1、實驗目的 1、了解HTTP協議及其報文結構 2、了解HTTP操作過程&#xff1a;TCP三次…

面試實戰,問題十三,Redis在Java項目中的作用及使用場景詳解,怎么回答

Redis在Java項目中的作用及使用場景詳解&#xff08;面試要點&#xff09; 一、Redis的核心作用高性能緩存層 原理&#xff1a;Redis基于內存操作&#xff08;引用[2]&#xff09;&#xff0c;采用單線程模型避免線程切換開銷&#xff0c;配合IO多路復用實現高吞吐&#xff08;…

Python - 100天從新手到大師 - Day6

引言 這里主要是依托于 jackfrued 倉庫 Python-100-Days 進行學習&#xff0c;記錄自己的學習過程和心得體會。 1 文件讀寫和異常處理 實際開發中常常會遇到對數據進行持久化的場景&#xff0c;所謂持久化是指將數據從無法長久保存數據的存儲介質&#xff08;通常是內存&…