Java工程師知識(shí)樹(shù) / Java基礎(chǔ)
數(shù)組簡(jiǎn)介:
數(shù)組(Array)是Java 語(yǔ)言中內(nèi)置的一種基本數(shù)據(jù)存儲(chǔ)結(jié)構(gòu),通俗的理解头镊,就是一組數(shù)的集合,目的是用來(lái)一次存儲(chǔ)多個(gè)數(shù)據(jù)。
數(shù)組是程序中實(shí)現(xiàn)很多算法的基礎(chǔ)锨匆,可以在一定程度上簡(jiǎn)化代碼的書寫新思。
備注:
- 數(shù)組的好處:數(shù)組里的每個(gè)元素都有編號(hào)剩愧,編號(hào)從0開(kāi)始猪叙,并且依次遞增,方便操作這些元素仁卷;
- 使用Java數(shù)組:必須先聲明數(shù)組穴翩,再給該數(shù)組分配內(nèi)存;
- 數(shù)組對(duì)應(yīng)在內(nèi)存中一段連續(xù)空間锦积。
- 數(shù)組元素必須是相同數(shù)據(jù)類型芒帕,也可以是引用數(shù)據(jù)類型,但是同一個(gè)數(shù)組中的元素必須是同一類數(shù)據(jù)類型丰介。
數(shù)組的聲明
Java數(shù)組有兩種聲明方式:
//數(shù)組的兩種聲明方式
int[] a;
int b[];
數(shù)組的初始化
Java數(shù)組有三種初始化方式:靜態(tài)初始化背蟆、用new聲明、用new聲明的同時(shí)初始化
//靜態(tài)初始化
int[] array1 = {4,5,6};
Integer[] b = {
new Integer(1),
new Integer(2),
new Integer(3),
3, //Autoboxing
3 //Autoboxing
};
//用new聲明哮幢,之后分別初始化數(shù)組中的每個(gè)元素带膀,聲明時(shí)需指定數(shù)組大小
int[] array2 = new int[3];
array2[0] = 1;
array2[1] = 2;
array2[2] = 3;
(注:如果數(shù)組元素類型為基本數(shù)據(jù)類型,在完成new操作之后家浇,數(shù)組中的元素會(huì)自動(dòng)初始化為空值本砰,可以直接使用.)
//用new聲明的同時(shí)初始化碴裙,這種方式不能指定數(shù)組的大小钢悲,數(shù)組大小由初始化列表中數(shù)據(jù)個(gè)數(shù)決定
int[] array3 = new int[]{1,2,3};
數(shù)組的遍歷
//for循環(huán)遍歷
System.out.print("for循環(huán)遍歷數(shù)組:");
for(int i = 0; i < 3; i++){
System.out.print(" " + arr[i]);
}
//foreach遍歷數(shù)組
System.out.print("foreach循環(huán)遍歷數(shù)組:");
for(int i: arr){
System.out.print(" " + i);
}
//Lambda表達(dá)式
Arrays.stream(arr).forEach(item -> {
System.out.print(item + " ");
});
基本數(shù)據(jù)類型對(duì)應(yīng)數(shù)組中元素的默認(rèn)值
int數(shù)組中元素默認(rèn)值是:0
float數(shù)組中元素默認(rèn)值是:0.0
double數(shù)組中元素默認(rèn)值是:0.0
char數(shù)組中元素默認(rèn)值是:'\u0000' 0
boolean數(shù)組中元素默認(rèn)值是:false
public static void main(String[] args) {
byte arrByte[] = new byte[1];
for (int i = 0; i < arrByte.length; i++) {
System.out.println("arrByte ==> "+arrByte[i]);
}
short arrShort[] = new short[1];
for (int i = 0; i < arrShort.length; i++) {
System.out.println("arrShort ==> "+arrShort[i]);
}
int arrInt[] = new int[1];
for (int i = 0; i < arrInt.length; i++) {
System.out.println("arrInt ==> "+arrInt[i]);
}
long arrLong[] = new long[1];
for (int i = 0; i < arrLong.length; i++) {
System.out.println("arrLong ==> "+arrLong[i]);
}
float arrFloat[] = new float[1];
for (int i = 0; i < arrFloat.length; i++) {
System.out.println("arrFloat ==> "+arrFloat[i]);
}
double arrDouble[] = new double[1];
for (int i = 0; i < arrDouble.length; i++) {
System.out.println("arrDouble ==> "+arrDouble[i]);
}
boolean arrBoolean[] = new boolean[1];
for (int i = 0; i < arrBoolean.length; i++) {
System.out.println("arrBoolean ==> "+arrBoolean[i]);
}
char arrChar[] = new char[1];
for (int i = 0; i < arrChar.length; i++) {
System.out.println("arrChar ==> "+arrChar[i]);
}
}
多維數(shù)組
二維數(shù)組:(其實(shí)是一個(gè)一維數(shù)組,它的每一個(gè)元素又是一個(gè)一維數(shù)組),
可以看做是一張表格舔株。
初始化分為動(dòng)態(tài)初始化和靜態(tài)初始化
動(dòng)態(tài)初始化
int[][] arr = new int[3][2];
定義了一個(gè)二維數(shù)組莺琳,其中有3個(gè)一維數(shù)組,每一個(gè)一維數(shù)組中有2個(gè)元素
靜態(tài)初始化
int[][] arr = new int{{1,2},{3,4},{5,6}};
int[][] arr = {{1,2},{3,4},{5,6}};
數(shù)組操作
判斷數(shù)組是否重復(fù)
求最大最小值
數(shù)組排序
數(shù)組的內(nèi)存分配
分配內(nèi)存空間
數(shù)組名=new 數(shù)據(jù)類型[數(shù)組長(zhǎng)度]载慈;
解釋:new關(guān)鍵字用來(lái)實(shí)現(xiàn)為數(shù)組或?qū)ο蠓峙鋬?nèi)存;數(shù)組具有固定的長(zhǎng)度惭等。獲取數(shù)組的長(zhǎng)度: 數(shù)組名.length
定義數(shù)組+分配內(nèi)存空間
數(shù)據(jù)類型[]數(shù)組名=new 數(shù)據(jù)類型[數(shù)組長(zhǎng)度];
解釋:定義數(shù)組時(shí)不指定長(zhǎng)度,分配空間時(shí)指定數(shù)組長(zhǎng)度办铡;如:String cities[] = new String[6];
數(shù)組元素
獲取數(shù)組元素:數(shù)組名[下標(biāo)值];
數(shù)組下標(biāo)從0開(kāi)始 比如:scores[0]=75辞做;
數(shù)組的內(nèi)存分配 棧內(nèi)存和堆內(nèi)存
解釋:如定義一個(gè)數(shù)組 int[]scores將在棧內(nèi)存中為scores 分配內(nèi)存空間琳要,其值是一個(gè)不確定的值。
當(dāng)執(zhí)行語(yǔ)句scores=new int[5]時(shí)秤茅,將在堆內(nèi)存分配連續(xù)5個(gè)空間稚补,每個(gè)空間4個(gè)字節(jié),用于存放整型數(shù)據(jù)框喳,其初始值為0课幕,然后將該段空間首地址,也就是第一個(gè)元素的地址五垮,比如0*3000乍惊,賦給scores變量。該地址相當(dāng)于一個(gè)指針放仗,指向堆內(nèi)存中分配的空間润绎。此時(shí)堆內(nèi)存中分配的5個(gè)空間可以分別使用scores[0],一直到scores[4]來(lái)表示。當(dāng)執(zhí)行四個(gè)賦值語(yǔ)句時(shí)诞挨,分別用指定值填充到對(duì)應(yīng)元素位置凡橱。如果此時(shí)將null值賦給scores時(shí),scores變量將不再指向任何位置亭姥,此時(shí)堆內(nèi)存中分配的空間就變成了垃圾稼钩,由垃圾回收器在某一時(shí)間進(jìn)行回收。
在方法中定義的變量达罗,包括基本數(shù)據(jù)類型變量和引用數(shù)據(jù)類型變量坝撑,都將在棧內(nèi)存中分配空間,當(dāng)超過(guò)變量作用范圍后粮揉,自動(dòng)回收巡李。
操作數(shù)組的工具類-Arrays
static int binarySearch(type[] a, type key) /*使用二分搜索法來(lái)搜索key元素在數(shù)組中的索引;若a數(shù)組不包括key扶认,返回負(fù)數(shù)侨拦。
(該方法必須已按升序排列后調(diào)用)。 */
static int binarySearch(type[] a, int fromIndex, int toIndex, type key) /*使用二分搜索法來(lái)搜索key元素在數(shù)組中
從fromIndex到toIndex的索引辐宾;若a數(shù)組不包括key狱从,返回負(fù)數(shù)。(該方法必須已按升序排列后調(diào)用)叠纹。*/
static boolean[] copyOf(type[] original, int newLength) //復(fù)制指定的數(shù)組見(jiàn)下面?zhèn)渥?static byte[] copyOfRange(type[] original, int from, int to) //將數(shù)組的指定范圍復(fù)制到一個(gè)新數(shù)組季研。
static boolean equals(type[] a, type[] a2) //如果兩個(gè)數(shù)組長(zhǎng)度相等和元素一一相等,則返回 true
static void fill(type[] a, type val) //將a數(shù)組所有元素都賦為val誉察。
static void fill(type[] a, int fromIndex, int toIndex, type val) //將a數(shù)組從formIndex 到tiondex索引之間的元素都賦為val与涡。
static void sort(type[] a) //sort(int[] arr)對(duì)指定的數(shù)組按數(shù)字升序進(jìn)行排序。
static void sort(type[] a, int fromIndex, int toIndex) //對(duì)指定數(shù)組的從formIndex 到tiondex索引之間的元素按數(shù)字升序進(jìn)行排序。
static String toString(type[] a) //返回指定數(shù)組內(nèi)容的字符串表示形式驼卖。多個(gè)數(shù)組元素之間用英文逗號(hào)或空格隔開(kāi)氨肌。
動(dòng)態(tài)數(shù)組
什么是動(dòng)態(tài)數(shù)組
? 數(shù)據(jù)結(jié)構(gòu)中順序表的物理實(shí)現(xiàn),同類數(shù)據(jù)元素的集合酌畜,在計(jì)算機(jī)中以連續(xù)的地址存儲(chǔ)儒飒,大小在創(chuàng)建時(shí)決定,但是可以改變檩奠。
為什么使用動(dòng)態(tài)數(shù)組
? 支持隨機(jī)訪問(wèn),查詢速度快桩了。但是插入和刪除都需要移動(dòng)元素,比起鏈表開(kāi)銷較大埠戳。如:java集合類中的ArrayList Vector等
動(dòng)態(tài)數(shù)組實(shí)現(xiàn)代碼(ArrayList原理)
/**
* 順序表的實(shí)現(xiàn)
*/
public class ArrayList<E> {
private Object[] data = null; // data: 用來(lái)保存此線性表數(shù)據(jù)的數(shù)組
private int capacity; // capacity: 線性表的容量
private int current; // current: 當(dāng)前數(shù)據(jù)的下標(biāo)
/**
* 初始化為聲明大小井誉,則設(shè)置為10。
*/
ArrayList() {
this(10);
}
/**
* 初始化線性表整胃,聲明保存數(shù)據(jù)的數(shù)組大小颗圣。
* @param initialSize 順序表的初始化大小
*/
ArrayList(int initialSize) {
if (initialSize >= 0) {
this.capacity = initialSize;
data = new Object[initialSize];
current = 0;
} else {
throw new RuntimeException("初始化大小不能小于0:" + initialSize);
}
}
/**
* 在線性表的末尾添加元素,添加之前確認(rèn)線性表是否已滿
* @param e 待加入的元素
* @return
*/
public boolean AddElement(E e) {
ensureCapacity();
data[current] = e;
++current;
return true;
}
/**
* 檢查存儲(chǔ)數(shù)據(jù)的數(shù)組容量屁使,如果數(shù)組已經(jīng)滿在岂,則擴(kuò)充容量;否則不操作蛮寂。
*/
private void ensureCapacity() {
int index;
if (current == capacity) {
capacity *= 2;
Object[] newData = new Object[capacity];
for(index = 0; index < current; ++index) {
newData[index] = data[index];
}
data = newData;
}
}
/**
* 返回下標(biāo)為index的元素
* @param index 欲取得元素的下標(biāo)
* @return
*/
public E get(int index) {
validateIndex(index);
return (E) data[index];
}
/**
*
* @param index 待插入的位置
* @param e 待插入的元素
* @return
*/
public boolean set(int index, E e) {
validateIndex(index);
data[index] = e;
return true;
}
/**
* 驗(yàn)證下標(biāo)值是否合法蔽午,非法時(shí)拋出異常
* @param index 待驗(yàn)證的下標(biāo)值
*/
private void validateIndex(int index) {
if (index < 0 || index > current) {
throw new RuntimeException("無(wú)效的下標(biāo):" + index);
}
}
/**
* 返回當(dāng)前順序表的大小
* @return
*/
public int size() {
return current;
}
/**
* 在指定位置插入指定元素
* @param index 待插入的位置
* @param e 待插入的元素
* @return
*/
public boolean insert(int index, E e) {
validateIndex(index);
ensureCapacity();
for (int temp = current; temp > index; --temp) {
data[temp] = data[temp - 1];
}
data[index] = e;
return true;
}
/**
* 刪除下標(biāo)為index元素
* @param index 待刪除元素的下標(biāo)
* @return
*/
public boolean delete(int index) {
validateIndex(index);
for ( ; index < current - 1; ++index) {
data[index] = data[index + 1];
}
data[current - 1] = null;
--current;
return true;
}
@Override
public String toString() {
String str = "[ ";
for (Object o : data) {
if (o != null) {
str += o + " ";
}
}
str += "]";
return str;
}
}