▶ IntelliJ idea 下載和安裝(http://www.jetbrains.com/idea/)
▶ 新建項目(如圖),注意選擇 SDK 類型和位置
● 在 src 目錄中新建一個 Package,在該 Package 中新建一個 class,在編輯器中寫該類的一個函數(主函數)如圖,點擊右上角錘子可以 build,或者在 build 和 run 選項卡中選擇相應選項
● 執行結果
▶ 嘗試運行了書中的一個代碼(二分搜索與白名單),發現環境配置過程中有很多問題,姑且先把成功了的過程寫在這里,僅供參考。
● 工作目錄為 "testJava",文件目錄如下,IntelliJ Idea 中建立了包 package01 和其中的一個類 class01.java,源文件放在其中(原始代碼如下,大意是輸入白名單文件和待篩查文件,輸出白名單中不存在的值)。自動編譯生成的文件是 class01.class。輸入白名單數據 tinyW.txt,待篩查文件 tinyT.txt。
D:\CODE\JAVA\TESTJAVA │ testJava.iml │ ├─.idea │ misc.xml │ modules.xml │ workspace.xml │ ├─out │ └─production │ └─testJava │ └─package01 │ class01.class │ └─src └─package01 class01.java
1 package package01; 2 3 import java.util.Arrays; 4 5 import edu.princeton.cs.algs4.StdIn; 6 import edu.princeton.cs.algs4.StdOut; 7 import edu.princeton.cs.algs4.In; 8 9 public class class01 10 { 11 private class01() {} 12 13 public static int indexOf(int[] a, int key) 14 { 15 int lo = 0, hi = a.length - 1; 16 while (lo <= hi) 17 { 18 int mid = lo + (hi - lo) / 2; 19 if (key < a[mid]) hi = mid - 1; 20 else if (key > a[mid]) lo = mid + 1; 21 else return mid; 22 } 23 return -1; 24 } 25 26 @Deprecated 27 public static int rank(int key, int[] a 28 { 29 return indexOf(a, key); 30 } 31 32 public static void main(String[] args) 33 { 34 In in = new In(args[0]); 35 int[] whitelist = in.readAllInts(); 36 37 Arrays.sort(whitelist); 38 39 while (!StdIn.isEmpty()) 40 { 41 int key = StdIn.readInt(); 42 if (class01.indexOf(whitelist, key) == -1) 43 StdOut.println(key); 44 } 45 } 46 }
● 前提工作:JDK 版本和 JRE 版本要對應(https://www.oracle.com/technetwork/java/javase/downloads/index.html),否則會能編譯不能運行,報錯為 UnsupportedClassVersionError;安裝教材附帶的類庫 algs4(https://algs4.cs.princeton.edu/code/,拖到中間一些的部分),需要管理員權限運行,會自動下載和安裝到用戶目錄,設置環境變量。相關鏈接(https://blog.csdn.net/fsx892512592/article/details/6038448,https://blog.csdn.net/u014629433/article/details/51593164,https://blog.csdn.net/u011240877/article/details/52457904)
● 使用命令行進行操作:將輸入文件 tinyW.txt 和 tinyT.txt 放到 src 目錄下,如圖所示。這里有若干可以說的事情:
① 設置環境變量 CLASSPATH 為 "." 以及 algs4.jar 的絕對路徑,可以在我的電腦的屬性里添加,也可以在命令行里臨時添加,還可以在 javac 命令中以選項的方式添加;有說法認為需要附上當前目錄 ".",我測試中有的代碼需要加,有的代碼不需要,以防萬一還是加上吧。如果不添加環境變量,則編譯報錯 "程序包edu.princeton.cs.algs4不存在" 以及后續的 "找不到符號XXX"(程序用到了 algs4 中的 In,StdIn,StdOut 等方法),如下圖所示。相關鏈接(https://blog.csdn.net/skyebefreeman/article/details/56495637)
D:\Code\Java\testJava\src\package01>javac class01.java // 不添加環境變變量的編譯 class01.java:5: 錯誤: 程序包edu.princeton.cs.algs4不存在 import edu.princeton.cs.algs4.StdIn; ^ class01.java:6: 錯誤: 程序包edu.princeton.cs.algs4不存在 import edu.princeton.cs.algs4.StdOut; ^ class01.java:7: 錯誤: 程序包edu.princeton.cs.algs4不存在 import edu.princeton.cs.algs4.In; ^ class01.java:34: 錯誤: 找不到符號 In in = new In(args[0]); ^ 符號: 類 In 位置: 類 class01 class01.java:34: 錯誤: 找不到符號 In in = new In(args[0]); ^ 符號: 類 In 位置: 類 class01 class01.java:39: 錯誤: 找不到符號 while (!StdIn.isEmpty()) ^ 符號: 變量 StdIn 位置: 類 class01 class01.java:41: 錯誤: 找不到符號 int key = StdIn.readInt(); ^ 符號: 變量 StdIn 位置: 類 class01 class01.java:43: 錯誤: 找不到符號 StdOut.println(key); ^ 符號: 變量 StdOut 位置: 類 class01 8 個錯誤
② 代碼首行寫了包名,運行時需要退到含有完整包名那一層目錄再運行。實測代碼中不加包名(把源代碼第一行注釋掉)仍能正確編譯,但是運行時會出現下面的效果,總之都無法加載主類(注意是兩種錯誤)。相關鏈接(https://www.zhihu.com/question/36537093,http://www.cnblogs.com/wangxiaoha/p/6293340.html,https://blog.csdn.net/codefellow/article/details/76601885,https://blog.csdn.net/u014427391/article/details/79743318,https://www.cnblogs.com/xyhz0310/p/6803950.html)
D:\Code\Java\testJava\src\package01>java class01.class tinyW.txt < tinyT.txt // 內層執行,代碼無包名 錯誤: 找不到或無法加載主類 class01.class 原因: java.lang.ClassNotFoundException: class01.class D:\Code\Java\testJava\src\package01>java package01.class01.class tinyW.txt < tinyT.txt // 內層執行,代碼有包名 錯誤: 找不到或無法加載主類 package01.class01.class 原因: java.lang.ClassNotFoundException: package01.class01.class D:\Code\Java\testJava\src\package01>cd .. D:\Code\Java\testJava\src>java class01 tinyW.txt < tinyT.txt // 外層執行,代碼無包名 錯誤: 找不到或無法加載主類 class01 原因: java.lang.ClassNotFoundException: class01 D:\Code\Java\testJava\src>java package01.class01 tinyW.txt < tinyT.txt // 外層執行,代碼有包名 錯誤: 找不到或無法加載主類 package01.class01 原因: java.lang.NoClassDefFoundError: class01 (wrong name: package01/class01)
③ 同時使用輸入文件和重定向將兩個文件喂給程序,輸出了正確的結果,這里沒有太大問題。
● Idea 中先准備庫路徑(類似添加環境變量):File → Project Structure → Modules → 右邊的 "+" → JARs or directories → 選擇上面安裝的 algs4.jar(C:\User\Username\algs4\algs4.jar)→ 左邊 □ 不清楚是否要勾上,右邊的 Compile / Run / Test / Provided 不清楚要選哪個,姑且選了 compile。相關鏈接(https://blog.csdn.net/t95921/article/details/53585225)
● 點擊原諒錘編譯,生成字節碼文件在 out 目錄下,缺少庫則會報錯,缺少包名仍能正確編譯
● 設置運行時配置(原諒錘右邊的框)如下圖。寫了主類(好像必填),輸入參數(注意輸入文件的相對路徑是相對工作目錄而言的,不要像上面 cmd 方式那樣放進 src 或 out 目錄),工作目錄,類路徑,其他沒有改動
● 至此,程序能夠正常開始運行,但還有點問題。
① 直接運行會發現程序會卡在 while (!StdIn.isEmpty()) 。理由是此時 Std 中內容不明,反正找不到可以作為輸入結束的字符,所以會一直掛住。用 step into 去看會進入 StdIn.java ,如下所示,卡在 return 這一行上。需要運行時(卡住以后)在 運行窗口中手動補充結尾符 "^D"(Ecplise 或 Linux 環境中可能是 "^Z"),解決問題。相關鏈接(https://www.zhihu.com/question/62001393,https://blog,.csdn.net/dmbjzhh/article/details/80525487,https://stackoverflow.com/questions/18437181/simulate-input-from-stdin-when-running-a-program-in-intellij,https://stackoverflow.com/questions/34972425/executing-nothing-java-project-in-intellij-idea,https://stackoverflow.com/questions/14991760/stdin-isempty-java,http://www.1point3acres.com/bbs/thread-2463-1-1.html)
1 public final class StdIn 2 { 3 ... 4 5 public static boolean isEmpty() 6 { 7 return !scanner.hasNext(); 8 } 9 10 ... 11 }
② 源代碼使用運行參數是 "tinyW.txt < tinyT.txt",嘗試打印輸入參數,發現 arg[0] = "tinyW.txt";arg[1] = "<";arg[2] = "tinyT.txt",理論上應該沒有問題(主函數自行處理 "<" 后的重定向文件參數),不清楚原因,不能自動完成輸入。
③ 另一種解決方案,最后我把代碼改成如下所示(不耐煩用 StdIn 和重定向輸入,而是手工讀取和檢測邊界),運行參數為 "tinyW.txt tinyT.txt",能夠正確輸出結果。本章下一篇博客才成功使用教材自帶的 StdIn / StdOut 等方法,可以作為參考。
1 package package01; 2 3 import java.util.Arrays; 4 5 import edu.princeton.cs.algs4.StdOut; 6 import edu.princeton.cs.algs4.In; 7 8 public class class01 9 { 10 private class01() {} 11 12 public static int indexOf(int[] a, int key) 13 { 14 int lo = 0, hi = a.length - 1; 15 while (lo <= hi) 16 { 17 int mid = lo + (hi - lo) / 2; 18 if (key < a[mid]) hi = mid - 1; 19 else if (key > a[mid]) lo = mid + 1; 20 else return mid; 21 } 22 return -1; 23 } 24 25 @Deprecated 26 public static int rank(int key, int[] a) 27 { 28 return indexOf(a, key); 29 } 30 31 public static void main(String[] args) 32 { 33 In in = new In(args[0]); 34 In in2 = new In(args[1]); 35 36 int[] whitelist = in.readAllInts(); 37 int[] test = in2.readAllInts(); 38 39 Arrays.sort(whitelist); 40 Arrays.sort(test); 41 42 for(int i=0;i<test.length;i++) 43 { 44 int key = test[i]; 45 if (class01.indexOf(whitelist, key) == -1) 46 StdOut.println(key); 47 } 48 } 49 }
▶ 其他問題
● 修改項目的類名,要注意類文件名和代碼中用到類名的地方都要改掉
● 命令行 javac 默認支持 ASCII 編碼,代碼里有中文注釋要去掉,或者在 javac 命令中使用選項 -encoding UTF-8 來改變使用的編碼類型。