(四)初始值(化)的方式(java.util.Arrays)
**陣列一定要有位址(記憶體)才能做資料
2){ }=>動態輸出=>自己決定初始值
(動態建立初始值的方式)
語法:類型[]陣列名={值,...,...,...}; =>陣列類型和值的類型要一致
EX:
如果使用new建立陣列,填值得時候要一筆一筆建立(如下),
當資料很多又同時都要輸入值,一筆一筆去改初始值很麻煩,就要用動態建立
chi[0]=65;
 
**{}會配給記憶體,但只會做到stack,不會給heap區,
如下{}沒給值,可以compiler但是執行會出現exception
int []chi={};
System.out.println(chi);
System.out.println(chi[0]); //因為還沒有產生chi[0]
 
3)比較new和{}的差別
new會配給記憶體,且給索引值和初始值(即heap區)
{}只會配給記憶體(只做到stack,但沒給heap區)
=>{}是打一個值就出現一個
 
=>new則是一次出現全部
 
 
**使用 java.util.Arrays的sort()來排序,
會把數字從小到大,文字(限定英文)從a到z排列
ex:(要記得先在class上面import java.util.Arrays;)
int []chi={100,70,88,64,33};
System.out.println(chi);
System.out.println(chi[0]);
for(int i=0;i<5;i++){
     System.out.println(chi[i]);
}
System.out.println("=========================");
Arrays.sort(chi);  //用Arrays裡的sort功能把chi陣列重新排列
for(int i=0;i<5;i++){
     System.out.println("chi["+i+"]="+chi[i]);
}
 
**使用binarySearch()來查陣列中是否有我們需要的資料,
binarySearch()是傳值類的method,所以執行完會產生一個值,
要指定如何輸出這個值
int []chi={100,70,88,64,33};
//要先做排列再查資料不然查出來的結果會怪怪的,
//另外srot()是void不傳值類的method
Arrays.sort(chi);  
for(int i=0;i<5;i++){
     System.out.println("chi["+i+"]="+chi[i]);
}
//要給的參數(要查的陣列名稱,要查找的資料)
System.out.println(Arrays.binarySearch(chi,64));
System.out.println(Arrays.binarySearch(chi,71));
=>當查找之後有資料,就會把查到的索引碼回傳(chi[1]=64)
=>但如果找不到資料,會去跟陣列的資料作比對排列,
像例子中71應該是排在索引碼3的位置,也就是第四個,
它會對應到負整數第四個位置,也就是-4(取負的索引碼)
=>所以只要回傳的值為負的,就代表找不到資料
 
(五)length=>查詢陣列的元素個數(可以用在迴圈的限制條件上)
int []chi={100,70,88,64,33};
System.out.println(chi.length);
for(int i=0;i<chi.length;i++){
     System.out.println(chi[i]);
}
 
(六)多維陣列
語法:類型[][]陣列名=new 類型[n][m];
=>分組的概念
=>組織圖有幾階段分組就會有幾個[][]
=>多維陣列中的[][]位置可以改變ex: int[] grade []
ex:有3個人,每個人有國文和英文兩個成績
(一)可以分成兩組,國文和英文,每組有三個人
int[]chi=new int[3];
int[]eng=new int[3];
 
(二)用多維陣列簡化作法
int[][]grade=new int[2][3];  
=>在記憶體中的做法就是,先找到grade array,
發現裡面有兩組陣列(chi和eng),再看陣列裡面,各有3個元素
**第一層就是第一個[],第二層就是第二個[],
所以上面代表先分2組,每組3個(由2個陣列組合而成)
**如果是[3][2]則代表先分3組,每個組別裡面有2個元素(由3個陣列組合而成),
與上述是不同的
=>畫成組織圖如下
 
=>組織圖如下:陣列表示應為school[3][2][3]
 
*看多維陣列的記憶體位址,如上例grade[0]和grade[1]兩組陣列都有記憶體位址
=>陣列的stack和heap排列方式與物件相同
 
*用巢狀迴圈run
動態:
int[][]陣列名稱={{xx,xxx,xx},{xx,xxx,xx}}(以兩組為例)
=>代表先分兩組,每組有3個元素
int[][]grade={{56,77,88},{66,73,91}};  
for(int x=0;x<2;x++){
  for(int y=0;y<3;y++){
    System.out.println("grade["+x+"]["+y+"]="+grade[x][y]);
  }
}
**如果直接用int[][]grade={56,77,88,66,73,91}
=>會出現錯誤訊息,因為前面是2維,後面是1維
 
*使用.length
ex:
int[][]grade={{56,77,88,99 } , { 66,73,91,63}};
System.out.println(grade); 
System.out.println(grade[0]);
System.out.println(grade[0][0]);
*[[I=>兩個[[代表有兩層陣列,有幾個就代表有幾層陣列
不論是查 grade 或grade[0]結果都是
[[I@..... 或[I@0000=>代表後面都是接記憶體位置,
只有 grade[0][0]才是值
=>只有查到最後一層才會是值,前面都只會查到記憶體位置
ex:
int[][]grade={{56,77,88,99 } , { 66,73,91,63}};
System.out.println(grade.length);  //outputs 2
System.out.println(grade[0].length); //outputs 3
*grade.length,查出來結果為2是因為grade的下是兩組陣列:
 length是線性的,只能查一層
 grade[0].length,查出來的結果為3,因為兩組陣列中每一組都是3個元素
應用到迴圈(一) 
=>迴圈中x代表第一個[],y代表第二個[]
int[][]grade={{56,77,88,99},{66,73,91,63}};
for(int x=0;x<grade.length;x++){
for(int y=0;y<grade[x].length;y++){
     System.out.println("grade["+x+"]["+y+"]="+grade[x][y]);
}
}
(二)如果兩組內的元素數量不同,用.length就不需要調整迴圈
int[][]grade={{56,77},{88,99,66,73,91,63}};
for(int x=0;x<grade.length;x++){
     for(int y=0;y<grade[x].length;y++){
         System.out.println("grade["+x+"]["+y+"]="+grade[x][y]);
     }
}
 
 
(七)值;位址=>"="  (java中做這個事為了回收記憶體;null),要判斷是值還是位址的換算
1)傳值=>passed by values
2)傳址=>passed by address
=>判斷"="兩邊是值還是位置,如果是值,會把資料copy過去,但如果是位置,
會把左邊的位置砍掉(回收記憶體),因此左邊的資料會消失,要非常注意!!
當y=x時,會有兩種狀況:
若只是資料copy,則x還是x,y還是y,兩者沒有關聯
若是y被x取代,則當y改變,x也會改變
 
(一)用變數來看
int x=10;
int y=20;
System.out.println("x="+x);
System.out.println("y="+y);
System.out.println("==========");
y=x;
System.out.println("x="+x);
System.out.println("y="+y);
System.out.println("==========");
y=30;
System.out.println("x="+x);
System.out.println("y="+y);
=>當y=x時,因為x和y都代表一個值,是把x的資料copy給y的動 ,所以當y=1時,x1[0]還是=1
 
(二)用陣列來看
int[]x1={1,2,3};
int[]y1={4,5,6};
System.out.println("x1="+x1);
System.out.println("y1="+y1);
System.out.println("==========");
System.out.println("x1[0]="+x1[0]);
System.out.println("y1[0]="+y1[0]);
y1[0]=x1[0];
System.out.println("x1[0]="+x1[0]);
System.out.println("y1[0]="+y1[0]);
y1[0]=100;
System.out.println("x1[0]="+x1[0]);
System.out.println("y1[0]="+y1[0]);
System.out.println("==========");
=> y1[0]=x1[0];是做資料copy的動作,所以當y1[0]=100時,x1[0]還是=1
 
 
y1=x1;
System.out.println("x1="+x1);
System.out.println("y1="+y1);
System.out.println("x1[0]="+x1[0]);
System.out.println("y1[0]="+y1[0]);
y1[0]=100;
System.out.println("x1[0]="+x1[0]);
System.out.println("y1[0]="+y1[0]);
=>當y1=x1時,是把y1指到x1的位址,所以會發現y1和x1的記憶體位置相同了,
這時去print x1[0]和y1[0]都會=1
=>再讓y1[0]=100;則 x1[0]和y1[0]都會變成100,因為是相同的記憶體位置
 
**java回收記憶體的方式:因為值都沒有記憶體,有記憶體都會常駐,如果都沒有使用還是會暫ram的空間
(一)用指定位址的方式,把y1刪除
int[]x1={1,2,3};
=>x1,y1代表位址,x1[0],y1[0]代表值
int[]y1={4,5,6};
y1=x1;
(二)用null的方式,直接把y1回收
int[]x1={1,2,3};
int[]y1={4,5,6};
System.out.println("x1="+x1);
System.out.println("y1="+y1);
y1=null;
System.out.println("x1="+x1);
System.out.println("y1="+y1);
 
(八)Java的陣列個數為固定,無法事後增加
int[] x={10,20,30,52};
for(int i=0;i<x.length;i++)
{
     System.out.println(x[i]);
}
System.out.println(x[4]);
System.out.println(x); //改變前的x
x=new int[10];
System.out.println(x); //改變後的x
for(int i=0;i<x.length;i++)
{
     System.out.println(x[i]);
}
=>可以compiler,但是記憶體位置改變了,等於產生了新的陣列
=>代表把新的位置傳給x,把原本的資料給砍掉了(不要舊的陣列要換一個新的陣列)
=>新的陣列所有值都變成初始值了
若再去查x[4],System.out.println(x[4]);=>會出現exception
 
(九)與物件導向結合應用
1.先定義陣列=>名稱為統一(決定數量)
2.物件再個別新增內容=>實體化
實例(一):建置一個會員資料庫,有三個欄位name,add,tel
靜態做法:
addmember.java
假設我們要輸入一百筆資料,輸出時不用陣列變成要一筆一筆輸出太麻煩
(一)
member aa=new member("aab1","city","123456789");
member dd=new member("aab2","city","123456789");
member cc=new member("aab3","city","123456789");
aa.show();
dd.show();
cc.show();
=>如果要用陣列,先判斷是否為同一組
=>因為aa/dd/cc都是用同一張表member有共同的reference,可以用陣列來做
 
(二)
class addmember{
     public static void main(String args[]){
          member[] m1=new member[3];
     }
}
=>member[] m1代表用member這張表作一個陣列,
new member[3]則代表先決定數量,此時m會配有記憶體
=>m[0]/m[1]/m[2]是三個物件而不是變數,
但這時候new只做了一件事就是定義三個物件的名字為 m[0]/m[1]/m[2],
並沒有配記憶體
=>如果這時候去print m[0],會出現null
=>當陣列結合物件時,第一次new是定義名字的動作,
個別物件要再new一次才能決定記憶體位置,如下:
 
member[] m=new member[3]; //等於是做上面(一)等號左邊命名的動作
//這邊開始才是做(一) 等號右邊new的動作
m[0]=new member("aab1","city","123456789");  
m[1]=new member("aab2","city","123456789");
m[2]=new member("aab3","city","123456789");
for(int i=0;i<m.length;i++){
     m[i].show();
}
 
 
**兩次new與配給記憶體的步驟
(1)第1次new時,只是用一個記憶體位址存放 m[0]/m[1]/m[2]這三個名字,
但沒有配給記憶體
(2)第2次new時,才會配給記憶體位址和heap區
 
**單獨使用new的說明
member aa=new member("aab1","city","123456789");
new member("aab2","city","123456789"); //可以compiler
System.out.println(aa);
System.out.println(new member("aab2","city","123456789"));
=>兩筆資料在java中都視為已完成,第2筆會丟一個位址出來,
所以可以print,且print會show記憶體位置
 
member aa=new member("aab1","city","123456789");
new member("aab2","city","123456789");
aa.show();
new member("aab2","city","123456789").show();
=>因為第2筆也是新增一個物件(物件就會有記憶體位址),
因為有記憶體位置所以可以做.show()
=>因為機器判斷時看的不是aa這個名字,而是記憶體位址
 
動態作法
addmember.java
member[] m={
new member("aab1","city","123456789"),
new member("aab2","city","123456789"),
new member("aab3","city","123456789"),
new member("aab4","city","123456789")};
 
for(int i=0;i<m.length;i++){
     m[i].show();
}
=>如果只有 member[] m={};,這時只會配給記憶體位置,不會配給索引碼
實例(二):
UML和流程圖
需要做s[0]~s[3],共4筆
student.java
class student{
private String name;
private int chi;
private int eng;
private int sum;
private double ave;
 
student(String name,int chi,int eng){
if(chi>=0 && chi <=100 && eng>=0 && eng <=100){
this.name=name;
this.chi=chi;
this.eng=eng;
sum=chi+eng;
ave=sum/2.;
}else{
     System.out.println("國文英文分數需介在0~100");
}
}
void show(){
System.out.println("姓名:"+name+
"\t國文:"+chi+
"\t英文:"+eng+
"\t總分:"+sum+
"\t平均:"+ave);
}
}
addstudent.java
class addstudent{
public static void main(String args[]){
student[] s ={
new student("kelly",90,100),
new student("kent",87,78),
new student("sylvie",73,55) ,
new student("maggie",100,63)
};
for(int i=0;i<s.length;i++){
       s[i].show();
}
}
}
*用scanner作互動(用scanner不能用動態)
addstudent.java
import java.util.Scanner;
class addstudent1 {
public static void main(String args[]) {
     Scanner sc=new Scanner(System.in);
     System.out.println("請輸入人數");
     int n=sc.nextInt();
     student[] s=new student[n];
     for(int i=0;i<s.length;i++) {
         System.out.print("第"+(i+1)+"的姓名");
         String name=sc.next();
         System.out.print("第"+(i+1)+"的國文");
         int chi=sc.nextInt();
System.out.print("第"+(i+1)+"的英文");
int eng=sc.nextInt();
s[i]=new student(name,chi,eng);
}
for(int i=0;i<s.length;i++) {
     s[i].show();
}
     }
}
=>這邊的name,chi,eng可以用區域變數,
因為輸入後就會把值丟給s[0],s[1],s[2],s[3],完成後就消失沒有關係
 
 
 
 
 
 
 
 
 
 
 
 
 
 
arrow
arrow
    文章標籤
    java arrays value
    全站熱搜
    創作者介紹
    創作者 muchone 的頭像
    muchone

    簡單。生活。享受

    muchone 發表在 痞客邦 留言(0) 人氣()