文章目錄
-
- 查閱足迹
- 【坑】字元串中的路徑表示法
-
- 相對路徑
- 絕對路徑
- 【記】讀寫檔案時的善後工作
- 【記】Git指令初步
- 【坑】已知正多邊形内角求多邊形邊數
- 【記】小烏龜轉向問題
- 【記】凸包問題
- 【記】關于疊代器Iterator
- 【記】關系網絡的距離求解
- 【坑】使用疊代器進行疊代時,改變疊代對象
- 【記】break跳出多層循環
w(゚Д゚)w大的同學們你們好!老師又讓我們寫部落格了,終于寫完了實驗報告,程式健壯性需要考慮的東西很多,到最後腦子一片漿糊,邊寫報告邊寫部落格兩邊懵逼,(@_@?
抵制一切盲目互佬的行為,建構良好的開源生态環境
查閱足迹
先不多廢話了,也許在寫完報告後回來完善部落格,這裡先記錄一下在實驗過程中的查閱足迹:
- Eclipse寫JAVA的相對路徑總結
- Java throw:異常的抛出
- Java讀取txt檔案和寫入txt檔案
- java中向上向下及四舍五入取整的方法,double型強制轉換成int型的取整方法?
- 删除github中某個檔案夾
- git中出現“non-fast-forward”errors時的終極解決方案
- 關于HashSet的各種使用方法總結
- 凸包問題的五種解法
- java中資料字典的使用
- 菜鳥教程-Java Stack 類
- Java隊列(Queue)了解及使用
- 菜鳥教程-Java 執行個體 - 隊列(Queue)用法
- No JUnit tests found’ in Eclipse
- 在JAVA中如何根據枚舉索引值來擷取枚舉值(範型适用)
- java.util.ConcurrentModificationException 異常問題詳解
【坑】字元串中的路徑表示法
在Java中,或其它某些程式設計語言中,我們再進行檔案操作時,常常要用到一個字元串變量filepath來表示檔案路徑,小夥伴們注意了,字元串中可是有轉義字元的噢~
相對路徑
如果你想用相對路徑尋址的話,當然這是值得推薦的方式,同平台的可移植性較高。如果你用的Eclipse IDE的話,那麼項目路徑預設是在項目檔案夾内,在目前狀态下,諸如
src
bin
檔案夾都是和目前路徑平級的,這些檔案夾下再尋址就要用到斜杠或者反斜杠了。
可以注意到,Windows系統中,資料總管中的檔案路徑顯示都是反斜杠 \,像這樣:

而反斜杠在Java字元串中屬于轉義字元(在markdown标記語言和其它許多程式設計語言中都是這樣),那麼在用反斜杠時,切記連續鍵入兩個反斜杠,以忽略轉義!。
不過我們也可以用正斜杠 / 來寫目錄路徑,雖然在Windows中使用反斜杠,而正斜杠通常用于Linux系統中。
絕對路徑
不建議這種方式來描述檔案位置,可移植性差,極差。但它的斜杠要求和上面說的相同,隻是你需要從根目錄開始逐級尋址。
【記】讀寫檔案時的善後工作
在讀寫檔案時,我們可能會建立這樣的變量
FileReader reader = new FileReader(fileName);
BufferedReader br = new BufferedReader(reader);
記得在程式可能退出的位置之前,打上這樣的兩行,或者隻打下面的第二行:
br.flush();
br.close();
第一行的意思大概是清空緩沖區,這裡面有很多講究,沒有仔細探究。
第二行是把這個I/O流關閉,可以防止資源洩露,這行還是很重要的。
【記】Git指令初步
在初識Git時,有一些概念有必要了解一下。
- 本地倉庫。本地倉庫是在本地目錄時用
指令之後,生成的一個git init
隐藏檔案,它是你本次建立git倉庫的倉庫管理檔案。其中儲存着倉庫曆史記錄等倉庫相關資訊。.git
- 遠端倉庫。遠端倉庫通常是在網際網路上的一個伺服器(很龐大的伺服器),GitHub就屬于一個伺服器,也有人搭建自己的Git伺服器。當你用
指令把本地倉庫推送到遠端時,就把自己的本地倉庫備份到了網際網路上,如果你的倉庫類型是public公開的話,其他人也可以很友善地浏覽。git push
- 分布式版本控制系統。Git是典型的代表,與集中式不同,分布式的分布指的是既在本地儲存了倉庫,也在遠端伺服器儲存了倉庫,版本控制管理更加靈活,也是當下大勢所趨。
- Git Bash。Git Bash是下載下傳安裝Git後,我們應用Git的主要工具,起始還可以使用Git GUI,但是初學不建議使用GUI操作,用Bash操作有利于我們學習代碼指令。
在本次實驗中,我們的Git操作是這樣的:
- 先按照實驗環境聲明建立遠端倉庫,然後在本地某個目錄下打開Git Bash開始clone任務代碼,記下目标倉庫的HTTPS路徑(或SSH路徑),在相應目錄下Git Bash中clone。clone前要先使用指令
以初始化git倉庫,然後clone,git init
,然後任務相關代碼就到了該目錄下。git clone https://github.com/rainywang/Spring2019_HITCS_SC_Lab1.git
這裡有可能遇到clone速度慢的情況,可以參考個人總結部落格https://blog.csdn.net/qq_41662115/article/details/86993426.
- 然後你可以做實驗了。
- 做完實驗後開始送出。将遠端倉庫的HTTPS添加到辨別符
中。如果之前已經添加過,那麼就會出現如下fatal提示:origin
這步是為了用HIT Software Construction 2019spring Lab-1 總結
表示遠端倉庫,相當于在遠端和本地之間搭了一座橋。origin
- 為了上傳送出或更新送出我們在本地的項目開發,先将代碼上傳到暫存區,
即為将目前目錄下所有檔案上傳到暫存區。git add .
HIT Software Construction 2019spring Lab-1 總結 - 然後用
指令送出更新,-m參數後面可以添加描述本次送出資訊的字串。git commit
HIT Software Construction 2019spring Lab-1 總結 - 這時,本次送出就已經寫入到本地Git管理曆史中了。要想上傳到遠端倉庫,用這個。可能要輸入密碼,這個密碼是SSH密鑰,是一種安全的資訊傳輸協定。
HIT Software Construction 2019spring Lab-1 總結 - 然後在遠端倉庫中我們可以看到本次送出的資訊,和更改狀态。還可以檢視本地的送出曆史日志。下圖給出的是我的最新的幾次送出。
HIT Software Construction 2019spring Lab-1 總結
【坑】已知正多邊形内角求多邊形邊數
這是上一個問題的拓展,上一個問題描述是這樣的
已知正多邊形邊數,求内角度數
上一個問題的解決方法,我們國小的時候就學過公式了,設内角度數為 α α α,邊數為 n n n,那麼有 α = 180 × ( n − 2 ) ÷ n α = 180 \times (n - 2) \div n α=180×(n−2)÷n。這裡面有一個問題是, n n n既然作為分母,結果難免會出現除不盡的情況,比如說正七邊形,那麼我們在Java中做浮點數除法時,得到的浮點數類型結果,必然不是精确值,但這種精确程度我們也可以接受了。
但是,在做這個問題的時候,我們要求邊數 n n n,那麼結果是一個整數,我們會出現浮點數舍入到整數的情況。在沒有指定舍入方法的情況下,預設是向零舍入,正數向下,負數向上,這樣如果你在計算過程中得到的 n n n是5.99…的話,那麼結果就是5了,而不是應該舍入的6.
解決方案
- 先加0.5,再強轉為
類型int
- 用
方法來做四舍五入。Math.round()
public static int calculatePolygonSidesFromAngle(double angle) {
int sides = (int) Math.round(360 / (180 - angle));
return sides;
}
【記】小烏龜轉向問題
這段也算是一個比較麻煩的功能實作吧,跟二維平面上的幾何關系有關,數學知識,直接把我的實驗報告搬過來吧。
這部分要一個方法,calculateBearingToPoint,是在給定一個向量和y正半軸夾角,該向量是小烏龜的面朝向,再給定小烏龜的二維坐标,和目的坐标,求小烏龜想要到達目的地前,最少需要順時針旋轉的角度。
我在紙上對兩給點的方位給出了8種情況的分析,最終合并8種情況為4種情況,兩點互為上下或左右分别是兩種情況,這種情況比較特殊,考慮起來很簡單。再有就是兩點并不互為上下左右,這樣的話除了考慮目前點的朝向,計算旋轉角度時還要考慮兩點夾角,這裡就把兩點連線和水準線所夾的銳角作為參考,并認為這個銳角是-90°到90°之間的,記為β。這樣的話,如果目标點在目前點的一三象限方位,那麼β是正的,否則β是負的。合并四個方位發現,雖然一四象限和二三象限時的β正負各自不同,但是得到的結果是一樣的,是以最後是四種情況。
我的情況分析是這樣的:
- 兩點互為上下。
- 目标點在上
- 傳回(360-α)%360
- 目标點在下
- α在0~180°
- 傳回180-α
- α在180~360°
- 傳回540-α
- α在0~180°
- 目标點在上
- 兩點互為左右。
- 目标點在左
- α在0~270°
- 傳回270-α
- α在270~360°
- 傳回630-α
- α在0~270°
- 目标點在右
- α在0~90°
- 傳回90-α
- α在90~270°
- 傳回450-α
- α在0~90°
- 目标點在左
- 目标點在左上或左下
- α在0~270°
- 270-α-β
- α在270~360°
- 630-α-β
- α在0~270°
- 目标點在右上或右下
- α在0~90°
- 90-α-β
- α在90~270°
- 450-α-β
- α在0~90°
簡單的角度圖湊活看吧
【記】凸包問題
先描述一下問題。給定平面上一些點的二維坐标,要求一個盡可能小的點集,該集合中的點在平面上圍成一個凸多邊形,且該凸多邊形包含給定的所有點。
6.031給出的凸包問題建議算法,可以用外包裹算法,Jarvis算法。這個算法是這樣的,先找到給定點集的邊緣點,比如說最左下的那個點,以它作為凸包的起點,然後尋找第二個點,第二個點應該滿足和起點連線與x正半軸夾角最小,從第三個點開始周遊,從第一次周遊開始,将第一個找到的點記為P1,第二個找到的點記為P2,要尋找的下一個點記為P3,每次尋找P3時,應滿足P3P2和P2P1的夾角最小,這樣步進尋找,得到的邊連接配接起來可以囊括所有的點,直到找到的P3回到起點為止。
在建構凸包過程中,對P3的尋找,可能會遇到P2P3直線上有多個點,那麼就要找距離P2最遠的那一個,放進凸包中。還有就是隻有一個點和兩個點的情況,這時規定給定點全是凸包中的點,這時凸包是一個點,或是一條線。
附上角度示意圖。總是希望兩向量夾角θ是最小的,并且取最遠的那個點。
【記】關于疊代器Iterator
對Set,List,Map.keySet這種具有集合性質的集周遊時,我們通常會使用兩種方式,一種是比較間接的for-each,另一種是建立一個Iterator對象,用它來做疊代工作。給出一個示例:
Iterator iterator = points.iterator();
while (iterator.hasNext()) {
next = iterator.next();
/* 找到給定點集最左下的點作為起點 */
if (next.y() < p1.y())
p1 = next;
else if (next.y() == p1.y() && next.x() < p1.x())
p1 = next;
}
它的疊代原理似乎是比較複雜的,簡單介紹來說呢,就是用hasNext()判斷疊代過程中,是否還有下一個疊代項,如果是,就繼續疊代,否則退出。擷取疊代對象用next()方法,這相當于一次步進。
問題在于,假設我們的某一疊代器的疊代工作由于某種原因中斷了,比如說以達成目标,break跳出循環while,而在接下來的工作中還需要疊代這同一個對象,那麼,我們的正确做法,應該是重置疊代器
iterator
,絕不能在沒有重置的情況,繼續使用它。
一個疊代器隻能用于一次疊代工作,如果它被中斷了(不能說終止,接下來可能還會用到),再回到它來疊代時,是繼續斷點疊代的。如果我們想重新周遊這一對象,就必須要
iterator = XXX.iterator()
來重置疊代器,開啟全新的周遊過程。
【記】關系網絡的距離求解
問題描述。規定一個無向圖,頂點代表人,邊代表邊上的兩點之間存在關系,若AB存在關系,則認定AB距離為1,若A到P有路,則認定AP距離為路的長度。若A到P無路,則認定AP距離為-1.
該問題的實質是圖問題中的最短路徑問題,要求的是源點到給定點的最短路徑,圖的各條邊權值均為1,圖為無向圖,但是後期可能要擴充到有向圖。點和邊手動輸入。要求兩個人的距離,也就是從一個人到另外一個人的最短路長。
使用的算法可以用廣度優先搜尋算法,記錄下源點到各點的路徑,然後從目标點回溯的源點,對路長計數,得出答案。
【坑】使用疊代器進行疊代時,改變疊代對象
問題:在做getsmarter問題的時候,我選擇了triadic closure來實作進一步的關注推測,對于三角關系的處理,我自然想到的是三層循環,判斷三者關系,錯誤代碼如下:
// BUGGY CODE
for(String A : guessFollowsGraphMap.keySet()) {
for(String B : guessFollowsGraphMap.get(A)) {
for(String C : guessFollowsGraphMap.get(B)) {
if(guessFollowsGraphMap.get(B).contains(A) && guessFollowsGraphMap.get(C).contains(B)) {
if(!guessFollowsGraphMap.get(A).contains(C))
guessFollowsGraphMap.get(A).add(C);
if(!guessFollowsGraphMap.get(C).contains(A))
guessFollowsGraphMap.get(C).add(A);
}
}
}
}
這裡會爆出這樣的異常
原因可以參考上述這位仁兄的部落格,小弟在這裡轉載過來了
java.util.ConcurrentModificationException 異常問題詳解
這個問題可能過于複雜,加上網上給出的多篇部落格,都是單線程下對疊代對象remove,或者多線程下的解決方案,對此,我的代碼中對疊代對象進行了add操作,沒有找到合适的解決方案,不過最後還是換了一種思維,實作了triadic closure的變相實作方式,修改後代碼如下:
HashMap<String, String> waitingAddedFollow = new HashMap<String, String>();
for(String A : guessFollowsGraphMap.keySet()) {
for(String B : guessFollowsGraphMap.get(A)) {
for(String C : guessFollowsGraphMap.get(B)) {
if(guessFollowsGraphMap.get(B).contains(A) && guessFollowsGraphMap.get(C).contains(B)) {
waitingAddedFollow.put(A, C);
}
}
}
}
for(String A : waitingAddedFollow.keySet()) {
String C = waitingAddedFollow.get(A);
if(!guessFollowsGraphMap.get(A).contains(C))
guessFollowsGraphMap.get(A).add(C);
if(!guessFollowsGraphMap.get(C).contains(A))
guessFollowsGraphMap.get(C).add(A);
}
【記】break跳出多層循環
當我們在使用多層
for
嵌套時,有可能要在内層循環使用
break
,希望跳出多層循環,但僅用
break
是做不到的。需要用到一個叫做循環标記的文法。比如:
firstloop: for(int i=1; i<10; i++)
secondloop: for(int j=1; j<10; j++)
thirdloop: for(int k=1; k<10; k++)
break secondloop;
上述代碼在執行到内層循環時,會直接跳出第二層循環,總的循環次數應該有
Eclipse的
ctrl+shift+f
賊強,有時間可以學習一下。