201711671203《Java程式設計》學習報告第十三週(完結,暫告一段落)
下週就考Java了,這學期的Java學習報告就到這裡結束了。寒假的時候可能會寫幾篇複習的,或者寫寫自己的程式吧。
教材內容總結
十四、圖形、影象與音訊
元件類Component類有一個方法public void paint(Graphics g),程式可以在其子類中重寫,當程式執行時,Java執行環境會用Graphics2D將引數g例項化,物件g就可以在重寫paint方法的元件上繪製圖形、影象。(圖形是向量的概念,基本元素是圖形指令;影象是點陣圖的概念,基本元素是畫素)
Graphics2D的“畫筆”分別使用draw和fill方法繪製和填充一個圖形。
(1)繪製基本圖形
在java.awt.geom包中的有很多類用來繪圖
new Line2D.Double(double x1,double y1,double x2,double y2); //建立起點(x1,y1)到終點(x2,y2)的直線 new Rectangle2D.Double(double x,double y,double w,double h); //建立一個左上角座標是(x,y)寬是w,高是h的矩形物件 new RoundRectangle2D.Double(double x,double y,double w,double h,double arcw,double arch); //建立左上角座標是(x,y),寬w,高h,圓角長軸和短軸分別是arcw和arch的圓角矩形物件 new Ellipse2D.Double (double x,double y,double w,double h); //建立一個外接矩形的左上角座標是(x,y),寬是w,高是h的橢圓物件 new Arc2D.Double(double x,double y,double w,double h,double start,double extent,int type); //建立圓弧物件。圓弧是橢圓的一部分,引數x,y,w,h指定橢圓的位置和大小,引數start和extent單位是度,從start的角度開始逆時針或順時針方向畫出extent度的弧,當extent為正時,為逆時針。type取值Arc2D.OPEN、Arc2D.CHORD、Arc2D.PIE決定弧是開弧、弓弧還是餅弧。 Graphics2D物件呼叫drawString(String s,int x,int y)方法從引數x、y指定的座標位置,從左向右繪製引數s指定的字串。 QuadCurve2D.Double類繪製二次曲線和三次曲線。如一條二次曲線需要三個點來確定,所以 QuadCurve2D curve = new QuadCurve2D.Double(50,30,10,10,50,100) //繪製一條斷電為(50,30)(50,100),控制點為(10,10)的二次曲線。 //三次曲線類似,需要四個點
java.awt包中的Polygon類可以建立空多邊形,然後多邊形呼叫addPoint(int x,int y)方法向多邊形新增頂點,下面例子繪製了太極圖和四邊形
import javax.swing.*; import java.awt.*; import java.awt.geom.*; class MyCanvas extends JPanel { public void paint(Graphics g) { Graphics2D g_2d=(Graphics2D)g; Arc2D arc=new Arc2D.Double(0,0,100,100,-90,-180,Arc2D.PIE); g_2d.setColor(Color.black); g_2d.fill(arc); g_2d.setColor(Color.white); arc.setArc(0,0,100,100,-90,180,Arc2D.PIE); g_2d.fill(arc); arc.setArc(25,0,50,50,-90,-180,Arc2D.PIE); g_2d.fill(arc); g_2d.setColor(Color.black); Ellipse2D ellipse=new Ellipse2D.Double(40,15,20,20); g_2d.fill(ellipse); arc.setArc(25,50,50,50,90,-180,Arc2D.PIE); g_2d.fill(arc); g_2d.setColor(Color.white); ellipse.setFrame(40,65,20,20); g_2d.fill(ellipse); g.setColor(Color.black); Polygon polygon=new Polygon(); polygon.addPoint(150,10); polygon.addPoint(100,90); polygon.addPoint(210,90); polygon.addPoint(260,10); g_2d.draw(polygon); } } public class Example14_1{ public static void main(String args[]) { JFrame win = new JFrame(); win.setSize(400,400); win.add(new MyCanvas()); win.setVisible(true); } }
(2)變換圖形
用AffineTransform類實現對圖形的平移、縮放或旋轉,先建立一個物件,然後該物件有下列三個方法實現對圖形變換操作
translate(double a,double b)將圖形在x軸方向移動a個畫素單位,a為正值時向右移動;y軸方向移動b個畫素單位,b是正值時向下。
scale(double a,double b),將圖形在x軸方向縮放a倍,y軸方向縮放b倍
rotate(doble number,doble x,double y)將圖形眼順時針或逆時針方向以(x,y)為軸旋轉number個弧度
(3)圖形的布林運算
兩個圖形進行布林運算之前,必須分別用這兩個圖形建立兩個Area區域物件,如
Area a1 = new Area(t1); Area a2 = new Area(t2); 這樣a1就是圖形t1所圍成的區域,a1呼叫add方法,a1.add(a2);之後,a1就變成a1和a2經過“或”運算後的區域。
public void add(Area r) //或 兩個圖形重疊部分
public void intersect(Area r) //與 兩個圖形的合併
public void exclusiveOr(Area rhs) //異或 a1去掉a1和a2的重疊部分
public void subtract(Area rhs) //差 兩個圖形非重疊部分
(4)繪製圖像
元件上可以顯示影象,如為了讓按鈕上顯示名稱為cat.jpg的影象,可以先用Icon類的子類ImageIcon建立封裝cat.jpg圖形檔案的ImageIcon物件,然後讓按鈕button呼叫方法設定其上的影象,除此之外,可以使用Graphics繪製圖像
1、載入影象
Java執行環境提供一個Toolkit物件,任何一個元件呼叫getToolkit()方法可以返回這個物件的引用。Toolkit類的物件呼叫方法Image getImage(String fileName)或者Image getImage(File file),可以返回一個Image物件,該物件封裝著引數file或引數filename指定的影象檔案。
2、繪製
影象被載入之後,就可以在paint()方法中繪製它。Graphics提供了幾個名為drawImage()的方法用於繪製圖像,他們功能相似,都是在指定位置繪製一幅影象,不同之處在於確定影象大小的方式、解釋影象中透明部分的方式、以及是否支援影象的剪輯和拉伸。
public boolean drawImage(Image img,int x,int y,ImageObserver);引數img 是被繪製的Image物件,x,y是要繪製指定影象的矩形的左上角所處的位置,observer是載入影象時的影象觀察器。呼叫該方法時,若元件的寬和高設計不合理,可能影象某些部分未能繪製到元件上。
(5)播放音訊
Java可以編寫播放.au、.aiff、.wav、.midi、.rfm格式的音訊程式。假設音訊問價hello.wav位於應用程式當前目錄中,那麼播放音訊的步驟是:
1、建立file物件, 2、建立URI物件 3、獲取URI物件 4、建立音訊物件 5 、 播放、迴圈和停止
clip.play() //開始播放
clip.loop() //迴圈播放
clip.stop() //停止播放
十五 泛型與集合框架
為實現如連結串列這種資料結構,需要實現往連結串列中插入結點或從連結串列中刪除結點的演算法,有些繁瑣。在JDK 1.2後,Java提供了實現常見資料結構的類,這些類成為Java集合框架。在JDK1.5後,Java集合框架支援泛型。
(1)泛型
泛型是在JDK 1.5中推出,目的是建立具有型別安全的結合框架,如連結串列、雜湊對映等資料結構。
1、泛型類宣告
class 名稱<泛型列表> 這樣宣告得到類稱作泛型類。如 class People <E> People是泛型類的名稱,E是其中的泛型,E可以是任何物件或介面,但不能是基本型別資料。泛型列表給出的泛型可以作為類的成員變數的型別、方法的型別以及區域性變數的型別
泛型類宣告和建立物件時,必須用具體的型別替換<>中的泛型,如下列例子
public class Example15_1 {
public static void main(String args[]) {
Circle circle=new Circle(10);
Cone<Circle> coneOne=new Cone<Circle>(circle);//建立一個(圓)錐物件
coneOne.setHeight(16);
System.out.println(coneOne.computerVolume());
Rect rect=new Rect(15,23);
Cone<Rect> coneTwo=new Cone<Rect>(rect);//建立一個(方)錐物件
coneTwo.setHeight(98);
System.out.println(coneTwo.computerVolume());
}
}
public class Circle {
double area,radius;
Circle(double r) {
radius=r;
}
public String toString() { //重寫Object類的toString()方法
area=radius*radius*Math.PI;
return ""+area;
}
}
public class Cone<E> {
double height;
E bottom; //用泛型類E宣告物件bottom
public Cone (E b) {
bottom=b;
}
public void setHeight(double h) {
height=h;
}
public double computerVolume() {
String s=bottom.toString();//泛型變數只能呼叫從Object類繼承的或重寫的方法
double area=Double.parseDouble(s);
return 1.0/3.0*area*height;
}
}
public class Rect {
double sideA,sideB,area;
Rect(double a,double b) {
sideA=a;
sideB=b;
}
public String toString() {
area=sideA*sideB;
return ""+area;
}
}
Java中的泛型類和C++的類模板有很大不同,上述例子中,泛型類中歐冠的泛型變數bottom只能呼叫Object類中的方法。
Java泛型主要目的是建立具有型別安全的資料結構。最重要的有點事,使用泛型類建立的資料結構,不必進行強制型別轉換,級不要求進行執行時的型別堅持。
(2)連結串列
連結串列這種資料結構的特點在資料結構一課中已經講明,這裡不贅述。
Java.util包中的LinkedList<E>泛型類建立的物件以連結串列結構儲存資料,連結串列使用add方法新增結點,結點是自動連線在一起,不需要操作安排結點中所存放的下一個或上一個結點,即連結串列是雙鏈表
LinkedList<E>泛型類實現List<E>泛型介面中的一些常用方法一般要使用介面回撥技術才可以實現。其中方法不一一贅述。
無論何種集合,應當允許使用者以某種方法遍歷集合中的物件,而不需要知道這些物件在集合中式如何表示及儲存。Java集合框架為各種資料結構的集合提供了迭代器。由於迭代器遍歷集合的方法在找到集合中的一個物件的同時,也的到待遍歷的後繼物件的引用,因此迭代器可以快速地遍歷集合。連結串列物件可以使用iterator()方法獲取一個iterator物件,該物件就是針對當前連結串列的迭代器。
import java.util.*;
public class Example15_2 {
public static void main(String args[]){
List<String> list=new LinkedList<String>();
for(int i=0;i<=60096;i++){
list.add("speed"+i);
}
Iterator<String> iter=list.iterator();
long starttime=System.currentTimeMillis();
while(iter.hasNext()){
String te=iter.next();
}
long endTime=System.currentTimeMillis();
long result=endTime-starttime;
System.out.println("使用迭代器遍歷集合所用時間:"+result+"毫秒");
starttime=System.currentTimeMillis();
for(int i=0;i<list.size();i++){
String te=list.get(i);
}
endTime=System.currentTimeMillis();
result=endTime-starttime;
System.out.println("使用get方法遍歷集合所用時間:"+result+"毫秒");
}
}
該例子比較了使用迭代器遍歷連結串列和get(int index)方法遍歷連結串列所用的時間。
程式可能需要對連結串列按著某種大小關係排序,一邊查詢一個數據是否和連結串列中某個節點的資料相等,Collections類提供用於排序和查詢的類方法如下
public static sort(List<E>list)該方法可以將list中的元素按升序排列。 int binarySearch(List<T>list,T key, CompareTo<T> c)使用折半法查詢list是否含有和引數key相等的元素,如果相等,方法返回和key相等的元素在連結串列中的索引位置(索引位置從0開始),否則返回-1。
String類實現了Compareable介面,規定字串按字典序比較大小,如果連結串列中存放的物件不是字串資料,那麼建立物件的類必須實現Compareable介面,即實現Compareable介面中的方法int compareTo(object b),來規定物件的大小關係。例子如下
import java.util.*;
class Student implements Comparable {
int height=0;
String name;
Student(String n,int h) {
name=n;
height = h;
}
public int compareTo(Object b) { // 兩個Student物件相等當且僅當二者的height值相等
Student st=(Student)b;
return (this.height-st.height);
}
}
public class Example15_4 {
public static void main(String args[ ]) {
List<Student> list = new LinkedList<Student>();
list.add(new Student("張三",188));
list.add(new Student("李四",178));
list.add(new Student("週五",198));
Iterator<Student> iter=list.iterator();
System.out.println("排序前,連結串列中的資料");
while(iter.hasNext()){
Student stu=iter.next();
System.out.println(stu.name+ "身高:"+stu.height);
}
Collections.sort(list);
System.out.println("排序後,連結串列中的資料");
iter=list.iterator();
while(iter.hasNext()){
Student stu=iter.next();
System.out.println(stu.name+ "身高:"+stu.height);
}
Student zhaoLin = new Student("zhao xiao lin",178);
int index = Collections.binarySearch(list,zhaoLin,null);
if(index>=0) {
System.out.println(zhaoLin.name+"和連結串列中"+list.get(index).name+"身高相同");
}
}
}
Collections類還提供了將連結串列中的資料重新隨機排列的類方法以及旋轉連結串列中資料的類方法
public static void shuffle(List<E>list) 將list中的資料按洗牌演算法重新排列 static void rotate(List<E>list,int distance) 旋轉連結串列中的資料 public static void reverse(List<E>list ) 翻轉list中的資料。
(3)堆疊 跳過
(4)雜湊對映 採用散列表的資料結構儲存資料,跳過
(5)樹集 TreeSet<E>類實現Set<E>介面的類,它的大部分犯法都是介面方法。具體結構跳過。
樹集結點的排列和連結串列不同,不按新增的先後順序排列。樹集用add方法新增結點,結點會按其存放的資料的“大小”順序一層一層地依次排列,同一層中的結點從左到右岸“大小”順序遞增排列,下一層都比上一層小。和連結串列中排序一樣,只有String類實現了Comareable介面中的compareTo(String s)方法,別的資料型別要另外實現方法。
(6)樹對映 TreeMap<K,V>實現了Map<K,V>介面,稱其為樹對映。樹對映使用public V put(K key,V value)方法新增結點,該結點不僅儲存資料value,也儲存器關聯的關鍵字key。和樹集不同,樹對映保證結點是按照節點中的關鍵字升序排列。
(7)自動裝箱和拆箱 JDK 1.5後,程式允許吧一個基本資料型別新增到類似連結串列等資料結構中,系統會自動完成基本型別到相應物件的轉換(自動裝箱)。當從一個數據結構中獲取物件時,如果該物件是基本資料的封裝物件,那麼系統自動完成物件到基本型別的轉換(自動拆箱)。下面例子展現其應用
import java.util.*;
public class Example15_10 {
public static void main(String args[]) {
ArrayList<Integer> list=new ArrayList<Integer>();
for(int i=0;i<10;i++) {
list.add(i); //自動裝箱,實際新增到list中的是new Integer(i)。
}
for(int k=list.size()-1;k>=0;k--) {
int m=list.get(k); //自動拆箱,獲取Integer物件中的int型資料
System.out.printf("%3d",m);
}
}
}
教材學習中遇到的問題
馬上考試了,課才剛剛上完,經過上週和這周的梳理,基本上對教材中所提到的知識都有了大概的印象,但仍有很多知識點處於一知半解的狀態,還有幾天時間,fighting吧
敲程式碼遇到的問題
很多啊......,之前作業有一道題是敲簡單地聊天室,關於while(scanner.hasnext())這個判斷語句完全沒有辦法,想要改成輸出指定字串後自動斷開伺服器連線,但改動之後就變成什麼都還沒輸入就自動斷開伺服器這種情況。在程式碼之路上艱難爬行......這個問題沒能解決,或許我應該使用元件來避開這個問題。
程式碼行數 | 部落格量 | 學習時長 | |
目標 | 3500 | 14 | 100 |
第一週 | 53 | 1 | 3 |
二 | 186 | 1 | 5 |
三 | 134 | 1 | 4 |
五 | 233 | 1 | 6 |
六 | 425 | 1 | 9 |
七 | 202 | 1 | 5 |
八 | 62 | 1 | 4 |
九 | 176 | 1 | 7 |
十 | 130 | 0 | 6 |
十一 | 56 | 1 | 8 |
十二 | 442 | 2 | 14 |
十三 | 462/2535 | 1/12 | 18/89 |