文章目錄
單鏈表的反轉,不用遞歸的方法。
import java.util.ArrayList;
public class ListRevert{
public static class Node{
private int val ;
private Node next ;
public Node(int val){
this.val = val;
}
}
public Node revertList(Node head){
ArrayList<Integer> list = new ArrayList<Integer>();
Node revHead = head;
while(head != null){
list.add(head.val);
head = head.next;
}
int i = list.size()-1;
Node newHead = null;
while(revHead != null){//賦值的方法
revHead.val = list.get(i);
if(i == list.size() - 1) newHead = revHead;//返回值
i--;
revHead = revHead.next;
}
return newHead;
}
public static void main(String[] args){
ListRevert listRevert = new ListRevert();
Node node = new Node(1);
node.next = new Node(2);
node.next.next = new Node(3);
Node node1 = listRevert.revertList(node);
while(node1 != null){
System.out.println(node1.val);
node1 = node1.next;
}
}
}
有序數組存在某個值,查找這個值的下標,有則輸出,無則輸出-1
public class SearchVal{
/** * 普通查找 * @param arr * @param number * @return */
public int searchval(int[] arr, int number){
int index = 0;
for(int i = 0; i < arr.length; i++){
if(number == arr[i]) return i;
}
index = -1;
return index;
}
/** * 二分查找 * @param arr * @param number * @return */
public int binarySearch(int[] arr, int number){
int len = arr.length ;
int left = 0;
int right = arr.length - 1;
int index = -1;
while(left <= right){//注意這里的臨界值:等號
int middle = (left + right) / 2;
if(number == arr[middle]){
index = middle;
break;
} else if(number > arr[middle]){
left = middle + 1;
}else if(number < arr[middle]){
right = middle - 1;
}else{
index = -1;
}
}
return index;
}
public static void main(String[] args){
SearchVal s = new SearchVal();
int[] arr = {1,2,3,4,5,6,7};
int number = 5;
int index = s.binarySearch(arr,number);
System.out.println(index);
}
}
C:\Users\xiaoqiu\Desktop>javac SearchVal.java//編譯為class文件
C:\Users\xiaoqiu\Desktop>java SearchVal//運行class文件不帶后綴
4
C:\Users\xiaoqiu\Desktop>
Java中靜態變量的初始化和存在哪里說一下
Java靜態變量一般存在於哪里
因為Java中的靜態變量相當於全局變量,可以被所有的線程共享,所以應該是放在方法區中(方法區中存儲的是已經被虛擬機加載的類信息,常量,靜態變量,即時編譯器編譯后的代碼等數據)
Java中的靜態變量什么時候進行初始化,如何初始化
Java中的靜態變量是在經過類加載中的“加載”=>"驗證"兩個階段之后的”准備“階段進行初始化的。
(准備階段:是正式為類變量分配內存並設置類變量初始值的階段)
但是這里的初始化只是設置該靜態變量的數據類型對應的零值,而不是人為指定的值。例如
public static int i = 23;
這里只會將i設置為0,而不是23
而23將會在解析階段之后的初始化階段進行賦值

但是如果該靜態變量為final類型,那么在通過javac編譯器編譯時,就會自動為該字段屬性中生成一個ConstantValue屬性。那么在准備階段就會根據ConstantValue屬性直接設置為23。例如
pulic static final int i =23;
JVM中堆和棧的區別
-
放的什么
堆里面放的是對象的實例,棧里面放的是Java方法的內存模型,每個Java方法在執行的同時就會創建一個棧幀,這個棧幀會隨着方法的調用到方法執行完成進行一個出棧和入棧的過程。(棧幀里面存放着方法的局部變量表,操作數棧,動態鏈接,方法出口等信息)
-
生命周期
堆是在虛擬機啟動的時候就會被創建,是Java虛擬機中最大的一塊內存
棧是創建線程的時候被創建,創建一個線程就會創建一個棧,所以是線程獨占,隨線程而生,隨線程而滅
-
線程共享
堆:所有線程共享
棧:線程獨占,一個棧只會屬於一個線程,每個線程都有自己獨立的棧
tcp/ip了解么,說下tcp的三次握手和四次分手(揮手)
什么是TCP
傳輸控制協議(英語:Transmission Control Protocol,縮寫:TCP)是一種面向連接的、可靠的、基於字節流的傳輸層通信協議,用戶數據報協議(UDP)是同一層內另一個重要的傳輸協議。
為什么要通過TCP進行傳輸
在因特網協議族(Internet protocol suite)中,TCP層是位於IP層之上,應用層之下的中間層。不同主機的應用層之間經常需要可靠的、像管道一樣的連接,但是IP層不提供這樣的流機制,而是提供不可靠的包交換。
應用層向TCP層發送用於網間傳輸的、用8位字節表示的數據流,然后TCP把數據流分割成適當長度的報文段。之后TCP把結果包傳給IP層,由它來通過網絡將包傳送給接收端實體的TCP層。
TCP/UDP協議的載體socket套接字
套接字包含必須的五種信息:連接使用的協議(TCP/UDP),本地主機的IP地址,本地進程的協議端口,遠地主機的IP地址,遠地進程的協議端口。
應用層通過傳輸層進行數據通信時,TCP會遇到同時為多個應用程序進程提供並發服務的問題。多個TCP連接或多個應用程序進程可能需要通過同一個 TCP協議端口傳輸數據。為了區別不同的應用程序進程和連接,應 用層可以和傳輸層通過Socket接口,區分來自不同應用程序進程或網絡連接的通信,實現數據傳輸的並發服務。
建立Socket連接至少需要一對套接字,其中一個運行於客戶端,稱為ClientSocket ,另一個運行於服務器端,稱為ServerSocket 。
套接字之間的連接過程分為三個步驟:服務器監聽,客戶端請求,連接確認。
服務器監聽:服務器端套接字並不定位具體的客戶端套接字,而是處於等待連接的狀態,實時監控網絡狀態,等待客戶端的連接請求。
客戶端請求:指客戶端的套接字提出連接請求,要連接的目標是服務器端的套接字。為此,客戶端的套接字必須首先描述它要連接的服務器的套接字,指出服務器端套接字的地址和端口號,然后就向服務器端套接字提出連接請求。
連接確認:當服務器端套接字監聽到或者說接收到客戶端套接字的連接請求時,就響應客戶端套接字的請求,建立一個新的線程,把服務器端套接字的描述發 給客戶端,一旦客戶端確認了此描述,雙方就正式建立連接。而服務器端套接字繼續處於監聽狀態,繼續接收其他客戶端套接字的連接請求。
TCP三次握手的具體過程

具體闡述過程如下:
- 首先客戶端client發送一個syn報文段給服務端,並設置syn一個序列號為x,此時客戶端進入SYN-SENT的狀態
- 當服務端server收到客戶端的連接請求之后,返回一個ACK確認收到的信號和自己的SYN報文段,ACK的序列號設置為x+1,SYN的序列號設置為y,此時server進入SYN-RECEIVED狀態
- client收到server的確認信號之后,還會再次返回一個ACK確認已收到的信號,並設置ACK的值為y+1,此時client進入established狀態,當server收到client的確認信號之后,也會進入established狀態,此時連接成功,就可以正常接收發送數據了。
為什么需要三次握手
因為TCP傳輸是可靠傳輸,那么在進行傳輸數據之前就必須要確定收發數據的雙方都具有收發數據的能力。而三次握手的目的:就是為了確認雙方都有收發數據的能力。
如果把client看作A,把server看作B
第一次: A->B,B確定A有發消息的能力。(這個時候A並不知道B收沒收到消息)
第二次: ->B && B->A,A確定B有收、發消息的能力。(此時B還不知道A有沒有收到自己的消息)
第三次: A->B,B確定A有收消息的能力。(現在B能夠確定已經收到了自己發的ACK消息)
另外一個種說法:
假如是兩次握手,那么針對網絡中由於延遲的連接請求,在新的連接已經釋放之后才到達server,那么此時server收到之后,向client返回一個確認信號,連接就建立了,此時server就會一直等待client發送數據,從而占用服務器的資源。從知乎上看到說其實是由於全局時鍾不同步的原因,所以必須要進行三次握手,才能保證收發數據的正確性。
TCP四次揮手的過程

具體闡述過程如下:
- client發送一個FIN報文x給server,進入FINISH_WAIT_1狀態,表示沒有數據要發送了
- server收到之后,返回一個ACK報文x+1,然后進入CLOSE_WAIT的狀態,client收到ACK報文后進入FINISH_WAIT_2狀態
- server再次發送一個FIN報文y給client,進入LAST_ACK狀態,表示server也沒有數據需要發送了,此時client進入TIME_WAIT狀態
- client返回一個ACK報文Y+1,server收到之后進入close狀態,client等待一段時間后沒有收到任何消息也進入close狀態(被動方先關閉,主動方才關閉)
為什么需要四次揮手
因為TCP是可靠的全雙工連接,兩次揮手只能證明一方沒有數據需要發送了,但是另外一方可能還需要發送信息,兩次揮手還處於半連接的狀態,所以雙方都需要向對方發送FIN報文,表示自己沒有數據需要發送了,才是真正的關閉連接。
TCP和UDP的區別和各自的應用
-
是什么
TCP面向連接的可靠的,面向字節流傳輸(先建立連接,再發送數據)
UDP面向無連接的、不可靠的、面向報文的傳輸(不與對方建立連接,直接發送數據)
-
為什么
TCP為什么是可靠的呢,就是因為它不僅有三次握手的連接機制,同時還有流量控制、擁塞控制等機制來保證了其可靠性
UDP卻沒有這些機制
TCP同時還是全雙工的
UDP可以是一對一,一對多,多對多,多對一
-
傳輸速度
TCP慢 UDP快
-
應用場合
TCP適用於傳輸的數據量大、可靠性要求高的場合,比如文件傳輸,遠程登陸
UDP適用於傳輸的數據量小,傳輸效率要求高,而對於可靠性要求不那么高的場合,比如QQ,語音電話,視頻電話,ping命令
http和https的區別,https加密的過程
-
加密:http明文傳輸,不提供任何方式的數據加密,不適合傳輸一些敏感信息比如銀行卡號
https可以通過SSL進行加密傳輸
-
端口:http默認80端口,https默認443端口
-
響應速度:http較快(主要是TCP三次握手的包),https(還要加上SSL握手的9個包)較慢
HTTPS的加密過程

-
客戶端在瀏覽器中輸入一個網址https://xxxx.com,這個時候就會自動連接到server的443端口
-
server端根據請求信息生成對應的公鑰和私鑰
-
server將數字證書(公鑰)發送給client,自己留下私鑰
-
client收到server的數字證書之后,驗證該數字證書是否有效,比如頒發機構,過期時間等,如果有效,就會生成一個隨機值,
-
client然后將這個隨機值放入公鑰里面,傳輸給server
-
server使用私鑰進行解密,獲取里面的隨機值
-
server將隨機值和私鑰進行對稱加密
-
server將對稱加密的內容發送給client
-
client使用自己私鑰進行解密,獲取內容
參考文獻
