學(xué)習(xí)目的
- 掌握數(shù)組的概念
- 掌握一維數(shù)組和二維數(shù)組的定義、初始化、賦值及循環(huán)遍歷
- 掌握數(shù)組的常用方法(復(fù)制和擴容)
- 掌握基本算法的原理和使用(冒泡排序、選擇排序、二分查找)
- 了解Arrays工具類的使用和常用方法
一.數(shù)組
- 概念
數(shù)組是一組數(shù)據(jù)的集合,是java提供的除了單個元素以外,可以存儲多個元素的集合。數(shù)組本身是一種引用數(shù)據(jù)類型,但數(shù)組中元素類型可以是基本類型,也可以是引用類型。但同一個數(shù)組只能存儲同一種類型,一個數(shù)組內(nèi)不能同時存儲基本數(shù)據(jù)類型和引用數(shù)據(jù)類型。 - 特點
- 數(shù)組本身作為對象<存儲在堆內(nèi)存中>,而元素則作為數(shù)組對象的屬性;
- 數(shù)組的長度在數(shù)組對象創(chuàng)建聲明后立即確定,過后無法再修改;
- 數(shù)組中的元素根據(jù)下標(biāo)來標(biāo)識,第一個元素從 0 開始,類推到最后一個元素的下標(biāo)為 n-1,可通過下標(biāo)來訪問數(shù)組元素。
- 用途
- 多元素的一個容器,一次可以存儲多個元素;
- 作為方法的形式參數(shù),當(dāng)一個方法的形式參數(shù)是一個數(shù)組時,可以傳遞進(jìn)來一個數(shù)組對象。
1.1 一維數(shù)組
- 定義
一維數(shù)組是指數(shù)組中存儲的是一個單一的元素,每個元素類型相同,且都只帶有一個下標(biāo)。其本質(zhì)上是一組相同類型數(shù)據(jù)的線性集合。 - 一維數(shù)組聲明
<不建議立即聲明數(shù)組長度[int]>
- 推薦:數(shù)組元素類型[] 變量名 = new 數(shù)組元素類型[數(shù)組元素個數(shù)];
- 數(shù)組元素類型 變量名[] = new 數(shù)組元素類型[數(shù)組元素個數(shù)]。
int[] i = {1,34,5,7,9,369};
//靜態(tài)初始化-第一種數(shù)組定義格式:推薦
int[] j = new int[5];
j[0] = 2;
j[1] = 4;
j[2] = 6;
j[3] = 8;
j[4] = 10;
//靜態(tài)初始化-第二種數(shù)組定義格式:不推薦
int j[] = new int[5];
j[0] = 2;
j[1] = 4;
j[2] = 6;
j[3] = 8;
j[4] = 10;
//一次定義多個數(shù)組
int[] a, b, c;
-
數(shù)組賦值圖解
一維數(shù)組賦值的內(nèi)存顯示.png
1.1.1 基本數(shù)據(jù)類型一維數(shù)組
- 概念
基本類型數(shù)組的元素只能是統(tǒng)一的基本數(shù)據(jù)類型,int類型數(shù)組只能存int元素,double類型數(shù)組只能存double元素。 - 數(shù)組定義格式
基本數(shù)據(jù)類型[] 變量名稱 = {基本元素 1,基本元素 2,...基本元素 n}
//靜態(tài)初始化-第一種數(shù)組定義格式:推薦
int[] i = {1,2,3,4,5};
-
基本數(shù)據(jù)類型一維數(shù)組圖解
基本數(shù)據(jù)類型的一維數(shù)組內(nèi)存模型.png
1.1.2 引用數(shù)據(jù)類型一維數(shù)組
引用類型數(shù)組的元素只能是統(tǒng)一的引用數(shù)據(jù)類型,String類型數(shù)組只能存String元素,Person類型數(shù)組只能存Person元素,Animal類型數(shù)組只能存Animal元素。
- 數(shù)組定義格式
引用數(shù)據(jù)類型類型 變量名稱[] = {引用元素 1,引用元素 2,...引用元素 n}
//靜態(tài)初始化引用類型數(shù)組,推薦該方式
String[] s1 = {"張三","李四","王五","趙六","錢七"};
//定義動態(tài)初始化數(shù)組,不推薦一開始就限定數(shù)組長度
String s3[] = new String[5];
//動態(tài)初始化引用類型數(shù)組(同上)
Person[] p = new Person[5];
for (int m = 0;m<p.length;m++){
Person ps = new Person();
p[m] = ps;
System.out.println(p[m].hashCode());
}
-
引用數(shù)據(jù)類型一維數(shù)組圖解
引用數(shù)據(jù)類型的一維數(shù)組內(nèi)存模型.png
1.1.3 數(shù)組初始化
- 定義
在定義數(shù)組時,若不對數(shù)組中元素手動賦值初始化,系統(tǒng)為該類型的每個元素賦 對應(yīng)數(shù)據(jù)類型的默認(rèn)值。 - 靜態(tài)賦值
在創(chuàng)建數(shù)組對象的時候直接賦值,<靜態(tài)初始化在編譯階段進(jìn)行,能減少運行時間>。 - 動態(tài)賦值
先創(chuàng)建聲明一個數(shù)組,后續(xù)根據(jù)元素下標(biāo)再逐個賦值,<動態(tài)初始化在運行時進(jìn)行>。 - 引用數(shù)據(jù)類型賦值
對于引用數(shù)據(jù)類型的數(shù)組,數(shù)組元素為對象內(nèi)存地址。因此賦予數(shù)組元素的值也是對象,不是賦予對象的屬性。
若沒有對引用數(shù)據(jù)類型的數(shù)組手動賦值,系統(tǒng)默認(rèn)引用類型元素的初始值為null,訪問該數(shù)組元素時會引發(fā)空指針異常。 -
引用類型數(shù)組賦值圖解
引用數(shù)據(jù)類型數(shù)組賦值.png
1.1.4 數(shù)組與多態(tài)
- 概念
一個元素類型定義為父類型的數(shù)組,實際存入數(shù)組的元素可以為子類型。但若要使用到子類型的方法時,需要使用instanceof符號進(jìn)行類型轉(zhuǎn)換。 - 代碼示例
public static void main(String[] args) {
// 創(chuàng)建一個Animal類型的數(shù)組
Animal a1 = new Animal();
Animal a2 = new Animal();
Animal[] animals = {a1, a2};
// 對Animal數(shù)組進(jìn)行遍歷
for (int i = 0; i < animals.length; i++) {
animals[i].move(); // 此處的move()方法是數(shù)組當(dāng)中Animal父類的move()方法
}
// 動態(tài)初始化一個長度為3的Animal類型數(shù)組
Animal[] ans = new Animal[3];
ans[0] = new Animal();// Animal數(shù)組中存放父類對象
ans[1] = new Cat(); // Animal數(shù)組中存放子類Cat
ans[2]= new Bird(); // Animal數(shù)組中存放子類Bird
for (int i = 0; i < anis.length; i++){
// 對取出來的對象進(jìn)行向下轉(zhuǎn)型,以調(diào)用子類重寫后的方法
if(anis[i] instanceof Cat){
Cat cat = (Cat)anis[i];
cat.catchMouse();
}else if(anis[i] instanceof Bird){
Bird bird = (Bird)anis[i];
bird.sing();
}
}
}
class Animal{
public void move(){
System.out.println("Animal move...");
}
}
// Cat子類
class Cat extends Animal {
public void move(){
System.out.println("貓在走貓步!");
}
public void catchMouse(){
System.out.println("貓抓老鼠!");
}
}
// Bird子類
class Bird extends Animal {
public void move(){
System.out.println("Bird Fly!!!");
}
public void sing(){
System.out.println("鳥兒在歌唱?。?!");
}
}
1.1.5 數(shù)組擴容
- 概念
數(shù)組從一開始定義時,就已經(jīng)限定了數(shù)組的長度,容量不再變。當(dāng)業(yè)務(wù)需求改變,需要存儲更多的數(shù)據(jù)元素時,舊數(shù)組已經(jīng)容納不下,因此要進(jìn)行數(shù)組擴容。 - 做法
- 新建一個大容量的數(shù)組,
- 將原數(shù)組中的數(shù)據(jù)一個一個拷貝到大數(shù)組當(dāng)中。
從舊數(shù)組的指定下標(biāo)開始,拷貝指定長度的元素,到新數(shù)組指定的下標(biāo)開始,粘貼拷貝過來的元素。
- 關(guān)鍵
調(diào)用System類中的arraycopy(Object src, int srcPos, Object dest, int destPos,int length)方法。
- Object src:舊數(shù)組對象
- int srcPos:舊數(shù)組下標(biāo)
- Object dest:新數(shù)組對象
- int destPos:新數(shù)組下標(biāo)
- int length:拷貝長度
-
數(shù)組擴容內(nèi)存圖解
數(shù)組擴容的內(nèi)存模型分析.png - 代碼示例
public static void main(String[] args) {
// java數(shù)組拷貝原理:arraycopy(舊數(shù)組,舊數(shù)組下標(biāo),新數(shù)組,新數(shù)組下標(biāo),拷貝長度)
//System.arraycopy(Object src, int srcPos, Object dest, int destPos,int length);
// 拷貝源(舊數(shù)組)
int[] src = {1, 11, 22, 3, 4};
// 拷貝目標(biāo)(新數(shù)組)
int[] dest = new int[20];
System.arraycopy(src, 1, dest, 3, 2);//從舊的下標(biāo)1開始,拷貝到新的下標(biāo)3下,長度為2
System.arraycopy(src, 0, dest, 0, src.length); //拷貝全部元素
for (int i = 0; i < dest.length; i++) {
System.out.println(dest[i]);
}
// 引用數(shù)據(jù)類型數(shù)組的拷貝
String[] strs = {"hello", "world!", "java", "oracle", "mysql", "jdbc"};
String[] newStrs = new String[20];
System.arraycopy(strs, 0, newStrs, 0, strs.length);
for (int i = 0; i < newStrs.length; i++) {
System.out.println(newStrs[i]);
}
//拷貝對象類型數(shù)組:存儲的對象內(nèi)存地址,拷貝的也是對象內(nèi)存地址
Object[] objs = {new Object(), new Object(), new Object()};
Object[] newObjs = new Object[5];
System.arraycopy(objs, 0, newObjs, 0, objs.length);
for (int i = 0; i < newObjs.length; i++) {
System.out.println(newObjs[i]);
}
}
- 注意點
- 數(shù)組擴容效率較低:數(shù)組擴容涉及到拷貝問題,在以后的開發(fā)中應(yīng)盡可能少的進(jìn)行數(shù)組拷貝;
- 在創(chuàng)建數(shù)組對象時預(yù)估長度:預(yù)估準(zhǔn)確數(shù)組定義的長度,可以減少數(shù)組的擴容次數(shù),提高開發(fā)效率。
1.2 string[] args數(shù)組
- 概念
在最常使用main方法中,main方法的參數(shù)列表也是一個數(shù)組,且是String類型數(shù)組。main方法雖然是由開發(fā)者編寫,由jvm自動執(zhí)行的一個方法,但main方法的參數(shù)數(shù)組args是由開發(fā)者編寫的調(diào)用程序傳入的。 - 位置
程序的主方法入口,main()方法的形式參數(shù)列表。 - 經(jīng)典代碼示例
//模擬系統(tǒng)登錄:使用main方法參數(shù)列表接收控制臺輸入的用戶名和密碼,并完成判斷
public class ArrayTest06 {
public static void main(String[] args) {
// 輸入?yún)?shù)必須為 2個,用戶名和密碼
if(args.length != 2){
System.out.println("請輸入用戶信息參數(shù),參數(shù)包括用戶名和密碼");
return;
}
// 獲取參數(shù)列表中的用戶名和密碼,判斷是否正確
String username = args[0]; // 取出用戶名
String password = args[1]; // 取出密碼
// 假設(shè)用戶名是admin,密碼是123表示登錄成功
//if(username.equals("admin") && password.equals("123")){ // 易出現(xiàn)空指針異常。
// 采用以下編碼風(fēng)格避免出現(xiàn)空指針異常(老程序員的一條編程經(jīng)驗)
if("admin".equals(username) && "123".equals(password)){
System.out.println("登錄成功,歡迎[" + username + "]回來");
System.out.println("歡迎您使用該系統(tǒng)....");
}else{
System.out.println("驗證失敗,用戶名不存在或者密碼錯誤!");
}
}
}
1.3 二維數(shù)組
- 定義
二維數(shù)組是指數(shù)組中的每個元素都是一個一維數(shù)組,本質(zhì)是以 數(shù)組 作為元素的數(shù)組。二維數(shù)組的使用類似于直角坐標(biāo)系,通過坐標(biāo)可以獲得指定元素。 - 二維數(shù)組聲明
- 數(shù)組元素數(shù)據(jù)類型[][] 變量名 = new 數(shù)組元素數(shù)據(jù)類型[][];
- 數(shù)組元素數(shù)據(jù)類型 變量名[][] = = new 數(shù)組元素數(shù)據(jù)類型[][];
//定義二維數(shù)組,推薦該方式
int[][] data = new int[][];
//c++定義二維數(shù)組,不推薦
int data[][] = new int[2][3];//定義一個2行,3列的二維數(shù)組
- 二維數(shù)組初始化
靜態(tài)初始化:int[][] data = {{元素1,元素2},{元素1,元素2,元素3,元素4}};
//初始化一維數(shù)組
int[] a = {1,2,4,45,6,68,3};
int[] b = {9,2,44,56,68,3,23};
int[] c = {8,2,4,7,2,435,7,68};
//靜態(tài)初始化二維數(shù)組
int[][] data = {{1,2,3,},{11,22,33},{1,2,4,8},{3,6,9,0}};
//二維數(shù)組的元素可以直接賦值"一維數(shù)組對象"
int[][] nm = {a,b,c};
- 二維數(shù)組的遍歷(分兩步)
- 先獲取"行":即先獲取二位數(shù)組的元素--一維數(shù)組,每一個一維數(shù)組本身作為一行;
- 獲取"列":獲取得到每一個一維數(shù)組后,開始遍歷一維數(shù)組的元素,每一個一維數(shù)組元素就是一列;
//定義一個具有三個元素的二維數(shù)組
int[][] nm = {{1,3,5},{2,4,6},{7,8,9}};
for (int i = 0;i<nm.length;i++){ //外層獲得元素是每一個一維數(shù)組
for (int j=0;j<nm[i].length;j++){ //內(nèi)層從每一個一維數(shù)組中獲取元素
System.out.println(nm[i][j]);//i=第幾個一維數(shù)組,j=第i個一維數(shù)組中的第j個元素
}
}
1.3 多維數(shù)組
- 定義
多維數(shù)組指的是數(shù)組中的每一個元素都是二維數(shù)組。 - 分類
- 一維數(shù)組:數(shù)組元素為普通數(shù)據(jù)類型
- 二維數(shù)組:數(shù)組元素為一維數(shù)組
- 三維數(shù)組:數(shù)組元素為二維數(shù)組
二. 數(shù)組和算法
- 算法概念
如何將文字描述轉(zhuǎn)換為有效率、高效率的代碼輸出。
2.1 冒泡排序(重點)
- 算法要求
對于一個無序的數(shù)組,要求按從小到大排序輸出。 - 實質(zhì)
利用水中相鄰泡泡比較的原理,最大氣泡最先升出水面。冒泡算法從數(shù)組最小下標(biāo)開始,每次比較下標(biāo) n 和 n+1兩個元素,若大小不相等則交換位置,繼續(xù)比較n+1和n+2下標(biāo)的元素。每一輪升出一個最大元素排最后,每下一輪減少一個元素進(jìn)行比較。 - 特點
- 一個數(shù)組有幾個元素a.length,就比較 a.length-1輪;
- 每一輪比較幾次,就交換幾次位置;
- 保證每一輪比較都有一個數(shù)移到最右邊(最后面),每下一輪可以減少一個元素的比較。
- 實現(xiàn)原理
- 先根據(jù)數(shù)組的長度,獲取總的排序輪數(shù) = 數(shù)組.length - 1;
- 根據(jù)每一輪的最大下標(biāo),確定每一輪比較的次數(shù),比較次數(shù) = 最大的下標(biāo)數(shù) - 1;
- 開始每一輪比較,從數(shù)組的最左邊開始<下標(biāo)為0開始>,逐個往右比較
取出第 0 號下標(biāo)的元素 和 第 1號下標(biāo)的元素比較
如果0 號數(shù)據(jù)大于1號數(shù)據(jù)則進(jìn)行交換,否則不進(jìn)行交換
在第一次比較交換了數(shù)據(jù)后的基礎(chǔ)上
取出1號下標(biāo)元素 和 2號下標(biāo)元素,重復(fù);
取出2號下標(biāo)元素 和 3號下標(biāo)元素,重復(fù);
取出3號下標(biāo)元素 和 4號下標(biāo)元素,重復(fù);
取出n-1號下標(biāo)元素 和 n號下標(biāo)元素,重復(fù); - 每完成一輪比較,可以確定一個最大的數(shù)排到最右邊,下一輪的比較則較少一個數(shù);
- 開始下一輪,最大下標(biāo) -1,比較次數(shù)-1;
- 重復(fù)以上步驟。
-
圖解
冒泡排序.png - 代碼實現(xiàn)
int[] data = {3,1,6,2,5};
//先根據(jù)數(shù)組長度,確定總的比較輪數(shù)
for (int i=data.length-1; i>0; i--) {
//開始每一輪的比較,第一輪有data.length-1個數(shù),每一輪減少一個
for (int j=0; j<i; j++) {
//開始比較,每一次都從下標(biāo)0開始和相鄰下標(biāo)比較,直到每次的最大下標(biāo)
//第一輪最大下標(biāo)為4,則依次比較下標(biāo)01,12,23,34
//第二輪最大下標(biāo)為3,則依次比較下標(biāo)0和1,1和2,2和3
//第三輪最大下標(biāo)為2,則依次比較下標(biāo)0和1,1和2
//第四輪最大下標(biāo)為1,則依次比較下標(biāo)0和1
//若前一個數(shù)大于后一個數(shù),兩數(shù)進(jìn)行交換
if (data[j] > data[j+1]) {
int temp = data[j];//前面較大值 暫存 到中間變量
data[j] = data[j+1];//將后面較小的值賦給前面一個下標(biāo)
data[j+1] = temp;//將暫存的最大值賦給后面一個下標(biāo)
}
}
}
//對排序完的數(shù)組進(jìn)行遍歷輸出
for (int i=0; i<data.length; i++) {
System.out.println(data[i]);
}
2.2 選擇排序(重點)
- 算法要求
對于一個無序的數(shù)組,要求按從小到大排序輸出。 - 實質(zhì)
利用相對固定的第一個位置的元素跟其他位置的所有元素比較,得出最小元素再和第一個位置的元素交換位置。 - 保證
默認(rèn)每一輪的比較都從左邊"第一個下標(biāo)"開始,保證了每一輪都有一個最小元素移到最左邊,下一輪減少一個元素的比較。 - 特點
對冒泡排序進(jìn)行改進(jìn),使交換次數(shù)減少,但比較次數(shù)沒有減少<每一輪比較只交換一次位置>。 - 選擇排序原理
- 先根據(jù)數(shù)組長度確定總的比較輪數(shù),總輪數(shù) = 數(shù)組.length - 1;
- 每一輪都從左邊的下標(biāo)開始,第一輪下標(biāo)0開始,第二輪下標(biāo)1開始,最后一輪數(shù)組.length - 1開始比較最后兩個數(shù);
- 定義初始下標(biāo):存儲每一輪從相對最左端開始的下標(biāo)
將下標(biāo)為 0 的元素 和 下標(biāo)為1,2,3,4的元素依次比較
如果找到比 初始下標(biāo)小 的元素,將該元素下標(biāo) 賦給 初始下標(biāo)
然后按當(dāng)前最小元素的下標(biāo),繼續(xù)往后依次比較
直到比較完每一輪中所有的元素 - 若初始下標(biāo)的元素就是最小值,不需要換位置;若不是,把最小的元素和初始下標(biāo)元素位置互換;
- 完成一輪后,初始下標(biāo)開始+1,初始下標(biāo)從0到1,1到2,2到3,n-2到n-1,重復(fù)以上步驟的比較。
-
圖解
選擇排序.png - 代碼實現(xiàn)
int[] data = {3,1,6,2,5,4,7};
//根據(jù)數(shù)組的長度確定,總的輪數(shù)<交換的次數(shù)>
for (int i=0; i<data.length; i++) {
int min = i;//每一輪比較的初始元素下標(biāo),從左邊開始
//每一輪從初始下標(biāo)與初始下標(biāo)的下一個元素開始進(jìn)行比較
for (int j=i+1; j<data.length; j++) {
//第一輪,初始元素下標(biāo)為0,則從下標(biāo)1元素開始比較;
//第二輪,初始元素下標(biāo)為1,則從下標(biāo)2元素開始比較;
//第三輪,初始元素下標(biāo)為2,則從下標(biāo)3元素開始比較;
//第n-1輪,初始元素下標(biāo)為n-2,則從下標(biāo)n-1元素開始比較
//若初始下標(biāo)元素大于比較的元素,則互換下標(biāo),繼續(xù)往下比較
if (data[j] < data[min]) {
min = j;//互換較小元素的 下標(biāo),繼而往下比較
}
}
//每完成一輪比較,進(jìn)行最小元素位置的交換
//若初始下標(biāo)就是最小下標(biāo),則不用交換
if (min != i) {
int temp = data[i];//將每一輪最小元素 賦給 中間量暫存
data[i] = data[min];//將初始位置的元素 互換到本輪最小元素位置
data[min] = temp;//將暫存的最小元素 換到 初始位置中
}
}
//遍歷最終排序的數(shù)組
for (int i=0; i<data.length; i++) {
System.out.println(data[i]);
}
2.3 二分查找(折半查找)
- 要求
給定一個已經(jīng)排序好的數(shù)組,查找出符合條件的一個元素。 - 查找方式
遍歷數(shù)組中的所有元素,逐個查找。 - 實質(zhì)
在一個排序好的數(shù)組中,找到期望值的元素下標(biāo),并輸出。 - 實現(xiàn)原理
- 對于一個已經(jīng)排好序的數(shù)組,從數(shù)組中查找一個期望值;
- 先初始化兩個變量,數(shù)組起始元素的下標(biāo)為0,數(shù)組末位元素的下標(biāo)為 數(shù)組.length - 1;
- 在已排序的數(shù)組里循環(huán)的二分 進(jìn)行查找;
- 循環(huán)條件:起始下標(biāo)元素 < 末位下標(biāo)元素;
- 執(zhí)行循環(huán)體:定義二分的中間下標(biāo) = ( 起始下標(biāo) + 末位下標(biāo) )/ 2
若中間下標(biāo)的元素和期望值相等,直接返回中間下標(biāo);
若中間下標(biāo)的元素 小于期望值,則從后半段數(shù)組中重新查找,且起始下標(biāo)更新為 當(dāng)前中間下標(biāo) + 1,末位下標(biāo)不變;
若中間下標(biāo)的元素 大于期望值,則從前半段數(shù)組中重新查找,且起始下標(biāo)不變,末位下標(biāo)更新為 當(dāng)前中間下標(biāo) - 1;
若數(shù)組中沒有這個期望值元素,直接返回 -1。
圖解
代碼解釋
public static void main(String[] args) {
//定義一個數(shù)組,必須有序,才能進(jìn)行二分查找
int[] data = {1,3,6,9,11,21,23,24,32,33,34,41};
//在數(shù)組中查找指定元素,返回該元素下標(biāo)
int index = binarySearch(data, 18);
System.out.println(index);//找不到目標(biāo)值18,返回-1
int index2 = binarySearch(data,11);
System.out.println(index2);//輸出目標(biāo)值下標(biāo)為:4
int index3 = binarySearch(data,33);
System.out.println(index3);//輸出目標(biāo)值下標(biāo)為:9
}
private static int binarySearch(int[] data, int i) {
//定義每一次二分的初始下標(biāo),下標(biāo)從0開始
int begin = 0;
//定義每一次二分的末位下標(biāo),最開始是數(shù)組的長度-1
int end = data.length - 1;
//判斷數(shù)組是否有序:起始下標(biāo)和末位下標(biāo)的元素大小
//不能用if控制語句,二分查找是循環(huán)、不斷取2的過程,要用while
while(data[begin] <= data[end]){
//定義中間元素的下標(biāo):中間 =(起始+末位)/2
int mid = (begin + end)/2;
//根據(jù)中間下標(biāo)的元素值 和 目標(biāo)值匹配
if (data[mid] == i){
return mid;
}else if (data[mid] >= i){
//中間元素值 大于 目標(biāo)值,下一次二分從前半段中查找
//前半段初始下標(biāo)不變,結(jié)束下標(biāo)為中間下標(biāo)-1
end = mid - 1;
}else if (data[mid] <= i){
//中間元素值 小于 目標(biāo)值,下一次二分從后半段中查找
//前半段的末位下標(biāo)不變,初始下標(biāo)為中間下標(biāo)+1
begin = mid + 1;
}
}
//執(zhí)行到這里,說明以上找不到目標(biāo)值,返回-1 表示查找失敗
return -1;
}
2.4 快速排序
原理
圖解
代碼解釋
2.5 Arrays工具類
- 概念
Arrays類是java提供的用來操作數(shù)組的各種方法的工具類。在該類中提供了 排序和搜索 數(shù)組的方法,在這些方法的底層已經(jīng)封裝好了算法實現(xiàn)。不需要開發(fā)者自己編寫。Arrays類還包含一個允許將數(shù)組作為列表 來查看的靜態(tài)工廠。 - 常用方法
- void sort(數(shù)組名):Arrays工具類封裝好的排序方法,調(diào)用該方法時,直接傳遞進(jìn)入一個數(shù)組即可對該無序數(shù)組進(jìn)行排序;
- int binarySearch(數(shù)組名, 期望值):Arrays工具類封裝好的二分查找方法,調(diào)用該方法時,直接傳遞進(jìn)入一個數(shù)組和期望值即可,返回期望值的下標(biāo)。
常見面試題
- 描述一下equals() 方法和 hashcode() 方法的關(guān)系?
答:
- 兩個對象hashCode()相等,對象不一定相等;
- 兩個對象 equals 相等,那么它們的 hashcode 一定相等。
- 兩個對象 equals 不相等,那么它們的 hashcode 并不要求不相等<一般建議不相等>;
- 對象在堆內(nèi)存中是存儲在HashSet或HashMap中的,HashSet底層采用的是 數(shù)組 + 單向鏈表組合存儲,數(shù)組中的每一個元素都是單向鏈表。每一個對象都是存儲在數(shù)組中,而對象調(diào)用hashCode()方法得到的哈希地址--經(jīng)過哈希算法的運算,最終得到對象在數(shù)組中的下標(biāo)。
- 但是由于每一個數(shù)組下標(biāo)上的元素都是單向鏈表,因此該位置上存在多個元素,該位置鏈表上的元素hashCode()都相同,但對象不一定相同。還需要比較對象的每一個屬性值,也就是需要使用 equals()方法。
- 當(dāng)兩個對象hashCode()不相同時,認(rèn)為兩個對象在數(shù)組中的下標(biāo)不一樣,因此兩個對象也不同。
- 使用數(shù)組模擬棧數(shù)據(jù)結(jié)構(gòu)?
/*使用一維數(shù)組,模擬棧數(shù)據(jù)結(jié)構(gòu):
1、這個棧可以存儲java中的任何引用類型的數(shù)據(jù)。
2、棧中提供push方法模擬壓棧(棧滿要有提示信息)
3、棧中提供pop方法模擬彈棧(??找灿刑崾拘畔ⅲ? 4、編寫測試程序,new棧對象,調(diào)用push pop方法來模擬壓棧彈棧的動作。
5、假設(shè)棧的默認(rèn)初始化容量是100
思路:
1、定義一個一維數(shù)組,有一個棧頂元素永遠(yuǎn)指向數(shù)組第一個下標(biāo)(數(shù)組未有數(shù)據(jù)時,初始化下標(biāo)是-1,棧頂元素也為-1)
2、push壓棧就是給一維數(shù)組添加一個元素(傳入?yún)?shù)),下標(biāo)往上加一,棧頂元素指向增加后的下標(biāo)
3、pop彈棧相當(dāng)于給一維數(shù)組刪除一個元素,實際只是棧頂元素往下移動,下標(biāo)往下減一
4、無論壓棧、彈棧都要先判斷該數(shù)組空間是否能已滿,或者是否還有元素可以彈出
*/
public class Stack{
//Object[] ojbs = new Object[100];
//定義一個可以存儲任何數(shù)據(jù)類型的一維數(shù)組
Object[] ojbs;
//棧幀:永遠(yuǎn)指向棧頂部元素,最初棧為空
//private int index = 0; // index==0,表示棧幀指向頂部元素上方
//private int index = -1; // index==-1,表示棧幀指向頂部元素
int index;//棧頂元素
public Stack() {
this.ojbs= new Object[10];//初始化數(shù)組的容量
index = -1;//初始化棧幀,并讓棧幀指向棧頂元素(-1表示棧一開始為空)
}
public Stack(Object[] ojbs){
this.ojbs = ojbs;
}
public Object[] getOjbs() {
return ojbs;
}
public void setOjbs(Object[] ojbs) {
this.ojbs = ojbs;
}
public int getIndex() {
return index;
}
public void setIndex(int index) {
this.index = index;
}
//壓棧--往數(shù)組中添加元素
public void push(Object obj){
if(index >= ojbs.length-1){ //下標(biāo)永遠(yuǎn)小于等于數(shù)組長度-1
System.out.println("棧已滿,不能再添加啦!");
return;
}
//棧未滿,可以壓棧。index初始=-1指向棧頂元素,壓入數(shù)據(jù)時,index自增+1;
index++;//index由-1變成0,元素可以壓入
ojbs[index] = obj;//將壓入元素賦給棧頂下標(biāo)
System.out.println(obj +"壓棧元素成功,棧幀指向:" + index);
}
//出棧不是刪除元素,只是棧頂元素(下標(biāo))往下移動,下標(biāo)改變代表刪除
public void pop(){
//if (ojbs.length<0){ //ojbs.length表示數(shù)組的長度,出棧不是刪除數(shù)組,因此長度不會小于0
if (index < 0){
System.out.println("棧已空,無法繼續(xù)刪除啦!");
return;
}
//棧未空,有元素可以繼續(xù)刪除
System.out.print(ojbs[index] + "出棧成功啦!");//先出棧
index--;//棧頂元素自減1
System.out.println("棧幀指向:" + index);
}
}
//測試
public static void main(String[] args) {
//創(chuàng)造一個棧對象,初始化數(shù)組容量為100,棧頂元素為-1
Stack st = new Stack();
//調(diào)用push(),測試壓棧
st.push(new Object());//java.lang.Object@4554617c壓棧元素成功,棧幀指向:0
...//此處重復(fù)壓棧8次
st.push(new Object());//java.lang.Object@330bedb4壓棧元素成功,棧幀指向:9
//數(shù)組初始容量只有10,超過10不能再壓棧
st.push(new Object());//棧已滿,不能再添加啦!
//調(diào)用pop(),測試出棧
st.pop();//java.lang.Object@330bedb4出棧成功啦!棧幀指向:8
...//此處重復(fù)出棧8次
st.pop();//棧已空,無法繼續(xù)刪除啦!
}






