2013年10月31日 星期四

ArrayList 移除 element 的問題

    今天查了 ArrayList 用法的時候,發現在 Javaworld 有人發了一篇 arraylist的移除問題,下面是他的 Sample Code
 
   ArrayList<integer> list = new ArrayList<integer>();
   list.add(2);
   list.add(2);
   list.add(3);
   list.add(1);
   list.add(2);
   System.out.println(list);

   for (int i=0; i<list.size(); i++){
      if(list.get(i)<3) {
         list.remove(i);
      }
   }
   System.out.println(list);

     原發問者想要將小於 3 的值全部移掉只剩下 3 這個元素,但是卻印出 [1 , 2],上面的的Sample Code 我有修改過,所以顯示為 [2,3,2] ,因為原程式在判斷條件小於3 的 if 後面多了分號 Orz。
     Anyway, 回到原來的問題,當你刪除一個元素時 size 也會跟著縮小,但是 i 的值卻會遞增,在 for 迴圈最後面加入除錯訊息,就可以知道為何印出 [2, 3, 2]。下面是我在 for 迴圈中加入除錯訊息所印出的資料:
i = 0 : [2, 3, 1, 2] size:4
i = 1 : [2, 3, 1, 2] size:4
i = 2 : [2, 3, 2] size:3

    要解決這個問題有下面三種方式

  1. 透過 Iterator 
  2. 透過 for 迴圈反向檢查,可以在 ConcurrentModificationException for ArrayList 中查到方式。
  3. 透過 CopyOnWriteArrayList

透過 Iterator 方式如下:
        
        Iterator<Integer> Allelement = list.iterator();
        while (Allelement.hasNext()) {
            if (Allelement.next() < 3) {
                Allelement.remove(); // 刪除最後 Iterator 所回傳的值,也就是目前所指到值
            }
        }
透過 for 迴圈反向檢查:
        
       for (int i = list.size() - 1; i >= 0; i--) {
            if(list.get(i) < 3){
                list.remove(i);
            }
        }

透過 CopyOnWriteArrayList:
        CopyOnWriteArrayList <Integer> list = 
                     new CopyOnWriteArrayList <Integer>();
        list.add(2);
        list.add(2);
        list.add(3);
        list.add(1);
        list.add(2);
        for (Integer val : list) {
            if (val  < 3) {
                list.remove(val);
            }
        }
請注意,使用 foreach 去詢訪 ArrayList 時,你不可以在 foreach 中 執行 remove,如果執行了應該會出現 java.util.ConcurrentModificationException 的例外訊息。


2013年10月23日 星期三

Scanner(System.in) 無法取的輸入的問題

    當你的只使用一個 Scanner(System.in) 在你的程式中並沒有甚麼問題,但是如果你有兩個類別都使用 Scanner(System.in) 來取得輸入時,最後使用 Scanner(System.in) 來取得輸入的類別是無法取得輸入,除非第一個使用的那個類別沒有呼叫close來關閉 Scanner。

    範例程式如下:
// InputDemo.java
import java.io.IOException;
import java.util.Scanner;

public class InputDemo {
    public static void main(String[] args) throws IOException {
        OtherInput otherInput = new OtherInput();

        int number = -1;
        Scanner scanner = new Scanner(System.in);
        
        // 嘗試執行下列敘述會得到IO例外訊息
        //System.out.println("System.in.available()" + System.in.available());
        
        System.out.print("Input a number:");
        if (scanner.hasNextInt()) {
            number = scanner.nextInt();
        }
        scanner.close();
        // 因為 scanner.nextInt() 沒有執行,所以 number 為 -1
        System.out.println("You input a number " + number);
    }
}

// OtherInput.java 
import java.util.Scanner;
public class OtherInput {
    public OtherInput() {
        Scanner scanner = new Scanner(System.in);
        
        int age = 0;
        String name = null;
        
        System.out.print("Please input your name:");
        if (scanner.hasNextLine()) {
            name = scanner.nextLine();
        }
        
        System.out.print("Please input your age:");
        if (scanner.hasNextInt()) {
            age = scanner.nextInt();
        }
        scanner.close();
        System.out.println("Your name: " + name + " and age: " + age);
    }
}

    在 Eclipse 下如果你沒有關閉 Scanner 會有一個警告訊息:"Resource leak: 'scanner' is never closed"。所以不建議不關閉 Scanner 物件。為什麼關閉 Scanner 物件會有問題呢? 因為當你執行 scanner.close() 時也會把 System.in 標準輸入也關閉掉,所以最後使用Scanner 物件的 calss 無法正常的取得輸入。
   你可以試著把上面的範例 InputDemo.java 中的 System.in.available() 註解符號拿掉,你會得到下列的例外訊息:
   Exception in thread "main" java.io.IOException: Stream closed
 at java.io.BufferedInputStream.getInIfOpen(Unknown Source)
 at java.io.BufferedInputStream.available(Unknown Source)
 at InputDemo.main(InputDemo.java:10)

   所以當你有多個類別要使用 Scanner(System.in) 取得輸入時,最好可以在主類別建立一個 Scanner 物件,然後將該物件傳遞給需要的類別,然後在主類別呼叫 Scanner 的 close 方法。

[其他參考]
java.util.NoSuchElementException - Scanner reading user input

Eclipse Console 視窗取得輸入的問題

     剛剛在嘗試了一下,發現是輸入法的問題,如果發現無法輸入可以將輸入切換到一般英文的模式,不要切換到有任何中文的輸入法。 : )

     在 Java 中要取得 Console 視窗輸入的文字可以透過 Scanner 物件來達到,今天如果你使用Eclipse 來開發時,當你的程式在取得輸入文字前,如果有先列印出一段提示文字時,你會發現 Eclipse 的 Console 視窗的游標會在最前面 (請參考下圖),並不會接在你所列印的提示文字後面,此時,如果你直接輸入任何文字嘗試取得輸入,會發現 Eclipse Console 視窗並不會顯示任何文字,且即便你按 Enter 想要結束輸入,Eclipse Console 視窗也不會有任何反應,此時你只能按停止執行或者重新執行程式來逃離這個狀況。

     要解決無法取得輸入的情況,當你執行程式時,必須先將游標移到正確的位置,然後再輸入,此時 Eclipse Console 視窗就可以正確的取得輸入的文字,注意,如果你的提示文字使用 println 來顯示,你必須移到下一行的開頭,如果使用 print 來顯示,則必須將游標移到提示文字的最後面才可開始輸入文字。

     範例程式如下:
import java.util.Scanner;

public class InputDemo {
    public static void main(String[] args) {
        int number = -1;
        Scanner scanner = new Scanner(System.in);
        System.out.print("Input a number:");
        
        if (scanner.hasNextInt()) {
            number = scanner.nextInt();
        }
        scanner.close();
        System.out.println("You input a number " + number);
    }
}


2013年9月25日 星期三

Java 查詢可用時區參數與設定時區

    Java 中可以透過 TimeZone 物件來查詢、設定 有關時區資訊。

查詢目前使用的時區:
TimeZone.getDefault().getID(); // Asia/Taipei
TimeZone.getDefault().getDisplayName(); // friendly name ex: 台灣標準時間

設定時區:
TimeZone tx = TimeZone.getTimeZone("Indian/Cocos"); // "Indian/Cocos" 就是 TimeZone ID
TimeZone.setDefault(tx);

列出可用時區:
String [] ids = TimeZone.getAvailableIDs();
for (String timezone : ids) {
    System.out.println(timezone + " " + 
          TimeZone.getTimeZone(timezone).getDisplayName());
}

   如果要取得目前日期時間可以透過 Calendar 物件取的相關訊息:
Calendar now = Calendar.getInstance();
int hour = now.get(Calendar.HOUR_OF_DAY);
int minute = now.get(Calendar.MINUTE);
int second = now.get(Calendar.SECOND);
int month = now.get(Calendar.MONTH);
int day = now.get(Calendar.DAY_OF_MONTH);
int year = now.get(Calendar.YEAR);
System.out.printf("現在是 %d/%d/%d %02d:%02d:%02d", 
    year, (month+1), day, hour, minute, second);

    要注意的是,Calendar 物件類別中的 MONTH 是用 0 到 11 來到表 1 月到 12 月,所以取得的數值要加 1 才會顯示正確。
 
    當你發現上面顯示的日期時間與你的電腦不符時,有可能是 Java 解譯器用錯時區設定;當 Java 解譯器不曉得目前的預設時區的話,會直接使用格林威治時間。

[相關資料]
[Java] 日期方法 (Date method)

懸置物件(dangling object)、懸置指標(dangling pointer)、懸置引用(dangling reference)

下面解釋來源: 程式語言結構 1

(1)懸置物件(dangling object):一個仍然存放資訊的記憶體空間,可是已沒有辦法可存取這個空間,則此空間便被稱為懸置物件。

(2)懸置指標(dangling pointer):懸置指標意謂指標指到一個不存在任何有意義資訊的記憶體空間。

(3)懸置引用(dangling reference):懸置引用意謂指標變數指到一個已經不存在的記憶體空間。如Pascal語言中,x是一個指標變數,當執行了dispose(x)後,(即將x所佔用的記憶體空間歸還給系統),若想引用x,則將造成懸置引用現象。

根據 Object-Oriented Programming in C++ 的解釋如下:

Dangling pointer
   Pointer point to a heap-dynamic variable that has been de-allocated.

Dangling reference
   Pointers that refer to something that no longer there and also occurs when a function return a pointer point to local variable.


[關鍵字]
dangling object dangling pointer dangling reference

[相關參考網站]

網路資源搜尋

Filesonic Hotfile Search - 可以找尋 影音及應用程式的搜尋引擎,但是中文沒有支援,所以你要搜尋的影片必須知道它的英文翻譯才行,該search engine 主要搜尋 hotfile.com 與 filesonic.com 檔案伺服器。

ShareDigger - File Search Engine - 可以搜尋 4filehosting.com、 Badongo.com、Depositfiles.com、Filefront.com、iFolder.ru、Megashares.com、Megaupload.com、Multiply.com、Rapidshare.com、Rapidshare.de、Rapidsharing.com、Rapidupload.com、Sendspace.com、TurboUpload.com、zshare.net網站上面所分享的檔案。

FileCrop - Search and Download Rapidshare Megaupload and Hotfile Files

Global FTP Search Engine: Global File Search Engine

YunFile- 網路檔案上傳伺服器,只能上傳檔案分享給其他人,沒有搜尋的功能,但是還是可以透過 Google來搜尋該伺服器目前有哪些分享的檔案。

http://hotfile.com/

4shared.com - 免費文件分享及儲存 有自己的資源搜尋引擎。讚!!

[Keyword]
File search engine

[相關文章]
多個免費檔案分流服務,讓你上傳一次就能儲存到一堆免費空間!
免費網路硬碟比一比
網路硬碟 | ㊣軟體玩家
【下載】: 免費網路硬碟空間50g【分享】 - yam天空部落
雲端大戰,6大免費網路硬碟誰最好用(上) | T客邦 - 我只推薦好東西
雲端大戰,6大免費網路硬碟誰最好用(下) | T客邦 - 我只推薦好東西

網路開放課程鏈結


麻省理工學院「開放式課程網頁」首頁

http://www.myoops.org/twocw/mit/index.htm

國立交通大學OpenCourseWare開放式課程
http://ocw.nctu.edu.tw/index.php 

哈佛進修學院遠距教育計劃
http://www.myoops.org/twocw/harvard/welcome/index.htm 

約翰霍普金斯大學彭博公共衛生學院開放式課程
http://www.myoops.org/twocw/jhsph/index.htm

日本開放式課程網頁聯盟
http://www.myoops.org/twocw/jocw/index.htm

台灣開放式課程網頁聯盟
http://www.tocwc.org.tw/

TBSCTS [專科]程式語言Youtube影片
http://www.youtube.com/view_play_list?p=06810CD71A86FACC

C 入門教學Youtube影片
http://www.youtube.com/view_play_list?p=0B6BF05869177563

中小企業網路大學校-數位學習
http://www.smelearning.org.tw/

我要自学网
http://www.51zxw.net/

MyOOPS開放式課程
http://www.myoops.org/main.php

C++ Tutorial by Zaychenok
http://www.youtube.com/watch?v=H1gV4JQI7OI&feature=BFa&list=PL0D836394D2FDDDB6&index=1

XoaX.net Video Tutorials
http://xoax.net/