大資料學習之路——java基礎(二)

qq_35831052發表於2019-04-01

方法

在java中是不區分函式和方法的,函式即是方法,方法也是函式。(物件導向中叫方法,程式導向中叫函式)

什麼是方法
某些情況下某些程式碼(200行左右)在進行大量重複,此時迴圈就不能滿足這個要求,此時可以將這些程式碼進行一次封裝,這個封裝就是“方法”。

DRY原則:Don’t Repeat Yourself(不要重複你自己的程式碼)。原因:重複意味著維護成本的增大。

方法格式

訪問許可權修飾符 [其他修飾符] 返回值型別 方法名(引數列表){
	方法體;
	return;
}

PS:在定義方法的時候,方法與方法之間是平級關係
詳細說明

訪問許可權修飾符:提供當前方法可以被誰呼叫(被誰訪問);有四種:public(公有的,最大許可權,誰都可以訪問),private(私有的),protected,default

其他修飾符:[]括起來的,可以不寫的,有四種:static(靜態的,屬於類)

返回值型別:當前方法完成某項功能之後,可以得到的結果.


1.無返回值型別--->void 此方法不會得到任何結果

2.有返回值型別-->2.1值型別(基本資料型別)  2.2引用型別(陣列,類,介面,集合,流等).

方法名:方法名要遵守識別符號命名規範,儘量使用動詞.
大駝峰:所有單詞的首字母大寫
小駝峰:第一個單詞字母小寫,後續每個單詞的首字母 例如:getNumber;

PS:絕對不能使用拼音,縮寫

(引數列表):形參–>形勢引數(定義變數,這個變數沒有具體值,只要這個方法不被呼叫,這個變數就不會有任何儲存空間);提供給方法使用,獲取外部傳遞進來的引數.

可以定義多個引數,使用逗號隔開
引數列表的組成:引數的資料型別 引數名,引數的資料型別 引數名…

PS:形參就當做一個變數,這個變數是等待外部進行賦值操作,並提供給內部方法使用的

方法簽名:每一個方法的方法簽名都是唯一的,若出現相同的方法簽名就會編譯報錯

方法簽名 = 方法名+引數列表

{}方法體(程式碼段):完成方法的具體邏輯
return關鍵字:可以終止方法或者帶回一個返回值

1.無返回值型別,即void:此時方法中可以使用return也可以不寫,方法都會終止.注意因為是無返回型別,所以不能在return後面新增任何具體的值

public static void show(){
	System.out.println("這是一個方法");
}

2.有返回值型別:此時必須使用return並且帶有一個返回值型別一致的值.

public static int show(){
	System.out.println("這是一個方法");
	return 1;
	//return "1"; 這樣錯誤,返回值型別與定義的不一致
}

PS:正常來說一個方法中只能執行一個return

呼叫方法
呼叫方法需要在方法內部
靜態方法,呼叫方式有兩種:

第一種:	方法名();

呼叫方法沒有返回值沒有引數
1.在同類中直接用方法名呼叫即可 2.不同類類名.靜態方法名呼叫方法

//列印99乘法表
class Method1 
{
	public static void main(String[] args) 
	{
		multiplicativeTable();
	}

	public static void multiplicativeTable(){
		for(int i=1;i<=9;i++)
		{
			for(int j=1;j<=i;j++){
				System.out.print(j+"*"+i+"="+i*j+"\t");
			}
			System.out.println();
		}
	}
}

PS:若當前方法中有引數列表,必須傳入對應的資料常量,變數或表示式或其他方法

傳進來的資料型別必須和形參的資料型別一致

傳進來的資料—>實參—>實際引數(有具體的值)

傳入引數的個數必須和形參個數一致

外部的實參名可以和形參名一致

若當前方法有返回值,可以選擇接收,可以不接收,若當前方法的返回值需要參與後續程式碼計算,必須接收,否則可以不接收

第二種:靜態屬於類,類可以呼叫靜態方法

類名.靜態方法名(引數);

不同點:在同一個類下面,可以不使用類名.方法名呼叫,在其他類中需要訪問當前類的靜態方法,就不許使用類名.方法名呼叫
PS:只要能列印方法,這個方法一定有返回值

public class Method2
{
	public static void main(String[] args) 
	{
		System.out.println("A所對應的小寫字母是"+LowLetter('A'));

	}

	public static char lowLetter(char capital)
	{
		return (char)(capital+32);
	}
}

方法記憶體圖
在這裡插入圖片描述
方法的過載

PS:在學習方法的時候是在間接地學習物件導向的封裝,在學習方法的時候就是在間接地學習物件導向的多型

方法多型—>同一個方法被不同引數所觸發得到的結果不一樣(過載)

方法名相同,引數列表不同—>過載

相同功能的方法,不需要定義不同的方法名,這樣不利於記憶;過載可以不用大量記錄方法名,可以通過同一個方法名呼叫方法,動態的通過引數來決定實現的邏輯

過載在API中大量應用

過載定義:
方法簽名=方法名+引數列表 這是唯一的,不可重複的
方法過載,即方法名相同,但是引數列表不同只要滿足下列一種即是過載

1.引數資料型別不同 2.引數個數不同 3.引數順序不同
只要滿足方法名和引數列表即為過載,其他都無關

避免出現以下情況:
二一性問題
遞迴(初級)

遞迴就是方法呼叫本身,遞迴對記憶體消耗很嚴重

遞迴就是相當於在方法體內部有一個隱式的迴圈

例如:
從前有座山,山上有座廟,廟裡有一個老和尚和一個小和尚,老和尚給小和尚講故事,講的是:從前有座山,山上有座廟,廟裡有一個老和尚和一個小和尚,老和尚給小和尚講故事,講的是:從前有座山,山上有座廟,廟裡有一個老和尚和一個小和尚,老和尚給小和尚講故事,講的是…

遞迴沒有出口即沒有結束的點,此時JVM會丟擲錯誤StackOverflowError棧溢位

逆向思維:

案例1:求1-10和

public class Test4 
{
	public static void main(String[] args) 
	{
		System.out.println(add(10));
	}	
	public static int add(int num)
	{
		if(num==1){
			return 1;
		}
		else{
			return num+add(num-1);
		}
	}
}

陣列

擴充套件:JVM記憶體圖

在這裡插入圖片描述
PS:JVM記憶體的劃分,根據人為的不同可以劃分為不同的樣式

程式計數器
當前執行緒所執行的位元組碼行號(執行到那個位置就在那個位置新增一個行號)

本地方法棧
為虛擬機器使用native方法所提供的服務(java中有一些方法是使用native修飾,沒有具體方法,它們是通過本地系統C++/C類庫進行實現)

java虛擬基棧(棧空間)
描述java方法執行的記憶體模型,每個方法執行的時候都會在棧中建立一個棧幀,就可以儲存區域性變數,操作棧,動態連結

PS:每一個方法,建立一個棧幀,戰陣中存放了當前方法的資料資訊,當前方法完成之後,還會進行彈棧

java堆
被所有執行緒共享的一塊儲存區域,在虛擬機器啟動的時候會建立,所有的物件都儲存在堆空間中

PS:再堆開闢空間,需要一個關鍵字–>new–>代表在堆空間中開闢了一塊新空間

方法區
所有執行緒共享的區域,儲存已被虛擬機器載入的類資訊(.class)\常量\靜態變數,即實時編譯所擁戴的資料都在這個區域

當出現比較大的資料量時,使用變數管理就不會特別方便了.

陣列是一種資料結構,能對大量資料進行統一管理,儲存在陣列中的資料是按照一定順序排列而成的

注意
1.陣列是一個定長的資料結構(一旦出現陣列大小,就不能儲存超過其他範圍內的資料)

2.陣列是開闢在堆空間,連續的一個記憶體空間

3.陣列中只能儲存相同資料型別的元素(值)
PS:不是絕對的,陣列也可以儲存所有Object型別的資料(子類)

陣列中元素的資料型別

基本型別和引用資料型別

引用資料型別:陣列,字串,自定義類,集合等
在這裡插入圖片描述
一定要記住無論是基本資料型別還是引用資料型別,建立陣列的時候,陣列中都會儲存預設值,null表示空,在堆空間中沒有開闢,這時不要使用,不然會產生NullPointerException異常

PS:NullPointerException異常空指標異常,使用了null進行了一些操作.

宣告陣列
語法:

陣列的資料型別是:資料型別+[]

//1.建立陣列的同時制定陣列的大小(動態賦值---先建立一空陣列,儲存的是預設值,再通過某個方法或計算得到具體的值,然後儲存到陣列中)
資料型別[] 陣列名 = new 資料型別[陣列長度]
如:int[] arr = new int[10];

//2.先宣告,再對陣列進行賦值(建立類時,陣列作為類的屬性存在)
資料型別[] 陣列名;
陣列名=new 資料型別[陣列長度];
如:int[] arr;
arr = new arr[10];

//3.在建立陣列時,指定陣列中元素
資料型別[] 陣列名 = new 資料型別[]{元素1,元素2,元素3....};
例:int[] arr = new int[]{1,2,3,4,5}
//陣列長度即為5

//4.第3種的簡化(靜態賦值)
資料型別[] 陣列名 = {元素1,元素2,元素3....};
例:int[] arr = {1,2,3,4,5};

陣列記憶體圖
在這裡插入圖片描述

int[] arr = new int[10];
System.out.pritln(arr);
//[I@70dea4e--->不是陣列地址,是一個字串[+陣列的元素資料型別+@+hashcode換算而來的

訪問陣列:通過下標完成
下標範圍:從0開始 到當(前陣列長度-1)結束

要修改陣列中第一個的元素

陣列名[下標值] = 要修改的值;
如:arr[0] = 100;

需要取出陣列中的值

int a = arr[0];

ArrayIndexOutOfBoundsException:陣列下標越界

arr.length	//獲取陣列長度

遍歷陣列

普通for迴圈–>運算元組下標

for(int i = 0;i<arr.length;i++){
	System.out.print(arr[i]);
}

增強for迴圈:foreach

for(int a:arr){	//將arr中的元素逐一賦值給a變數
	System.out.println(a);
}

PS:增強for迴圈不能對陣列進行賦值
陣列案例

氣泡排序:

		int[] arr = new int[10];
		//System.out.print(arr[10]);
		System.out.println("排序之前:");
		
		for(int i = 0;i<arr.length;i++) {		
			arr[i] = (int)(Math.random()*100+1);		
		}
		for(int i = 0;i<arr.length;i++) {
			System.out.print(arr[i]+"\t");
		}
		System.out.println();
		System.out.println("排序之後:");
		for(int i = 0;i<arr.length;i++) {
			for(int j=0;j<arr.length-i-1;j++) {
				if(arr[j]>arr[j+1]) {
					int tmp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = tmp;
				}
			}
		}
		for(int i = 0;i<arr.length;i++) {		
			System.out.print(arr[i]+"\t");		
		}

選擇排序:

	int[] arr = new int[10];
		//System.out.print(arr[10]);
		System.out.println("排序之前:");
		
		for(int i = 0;i<arr.length;i++) {			
			arr[i] = (int)(Math.random()*100+1);			
		}
		for(int i = 0;i<arr.length;i++) {
			System.out.print(arr[i]+"\t");			
		}
		System.out.println();
		System.out.println("排序之後:");
		for(int i = 0;i<arr.length;i++) {
			for(int j=i+1;j<arr.length;j++) {
				if(arr[i]>arr[j]) {
					int tmp = arr[j];
					arr[j] = arr[i];
					arr[i] = tmp;
				}
			}
		}
		for(int i = 0;i<arr.length;i++) {			
			System.out.print(arr[i]+"\t");			
		}

線性查詢:

/**
 * 查詢某個數在陣列中的位置
 * @param arr
 * @param num
 * @return 要找的數在陣列中的位置下標
 */
public static int linearSeekNumber(int[] arr,int num) {
	for(int i=0;i<arr.length;i++) {
		if(num==arr[i]) {
			return i;
		}
	}
	return -1;
}

二分查詢(必須先進行排序)

/**
 * 二分查詢
 * @param arr
 * @param num
 * @return
 */
public static int binarySearchNumber(int[] arr,int num) {
	int beginIndex = 0;
	int endIndex = arr.length-1;
	int middleIndex = (beginIndex + endIndex)/2;
	while(beginIndex<=endIndex) {
		if(num == arr[middleIndex]) {
			return middleIndex;
		}
		if(num<arr[middleIndex]) {
			endIndex = middleIndex-1;
			middleIndex = (beginIndex + endIndex)/2;
		}else {
			beginIndex = middleIndex+1;
			middleIndex = (beginIndex + endIndex)/2;
		}
	}
	return -1;	//返回-1表示沒有找到
}

Arrays工具類

//檢視當前陣列元素
String str = Arrays.toString(arr);
System.out.println(str);

//陣列排序
Arrays.sort(arr);
System.out.println( Arrays.toString(arr));

//二分查詢
int index = Arrays.binarySearch(arr,100);
System.out.println(index);

//複製陣列
/**
 *深拷貝:既賦值陣列內容,又複製陣列地址
 *淺拷貝:只是複製陣列內容,不復制陣列地址
 *num:要複製的長度(不能是負數)
 */
 int[] newArray = Arrays.copyOf(arr,5);
 System.out.println(Arrays.toString(newArray ));
//範圍內拷貝陣列
//包括開始,不包括結束 引數是下標 不能是負數 不能超出範圍
int[] newArray = Arrays.copyOf(arr,2,5);
System.out.println(Arrays.toString(newArray ));

注意:值型別可以使用==判斷兩個值是否相等,但是引用型別絕對不可以使用==對兩個引用進行判斷 若使用==判斷值型別,比較的是內容;若使用==對引用型別進行判斷,此時比較的是地址
比較兩個陣列的內容和大小是否相等

System.out.println("兩個陣列是否相等"+Arrays.equals(newArray ,arr));

相關文章