2013年12月3日

JAVA I/O處理

 I/O處理

我們可以使用Input/Output來讀取外部的檔案/資料(檔案、console、網路資料),java.io類別庫提供很多函式功能,提供程式設計師方便使用。在JAVA SE7 會新增java.nio主要是增加io新的函式功能。

  • IO Stream 
IO分為兩種接收資料與傳送資料的模式,

(1) 位元模式(Byte Stream)
位元模式下就是輸入或是輸出資料須均要以8bit的位元,要完成一個位元模組可以利用InputStream或是OutputStream來完成。

Name: 文字檔案複製
Desc : 將文字檔複製到另一個檔案
  FileInputStream fis = null ;
OutputStream fos = null ;
try{
fis = new FileInputStream("input.txt");
fos = new FileOutputStream("output.txt") ;
  int c ;
  while((c = fis.read())!= -1){
  fos.write(c);
  }
}finally{
  if(fis!=null){
    fis.close();
  }
  if(fos!=null){
    fos.close();
}
}

(2) 字元模式(Character Streams)
字元模式主要是利用Unicode來做傳輸,當我們利用Character Stream IO做傳送時,他會自動轉成為local character的文字集,大多的應用程式都是字元模式

Name: 文字檔案複製
Desc : 將文字檔複製到另一個檔案
  FileReader rd = null ;
FileWriter rw =null ;

try{
//宣告實體
int c ;
rd = new FileReader("input.txt") ;
  rw = new FileWriter("output.txt") ;
  while((c=rd.read())!= -1){
  rw.write(c);
  }
}catch(IOException ioe){

}finally{
  if(rd!=null){
  rd.close();
}
if(rw !=null ){
rw.close();
}
}

   在常見的狀況下,我們會讀取大的資料比較常會遇到,所以IO提供以行為單位的方式來存取,我們利用緩衝的IO來實做BufferedReader,我們利用BufferedReaer的功能來實做一個簡單資料庫的功能。

Name: 簡單資料庫
Desc : 利用文字檔建立資料庫,來存取資料
 public class SimpleDataBase {
private static Map<String, String> map = new HashMap<String, String>() ;
public static void main(String[] args) throws IOException {

BufferedReader breader = null ;
BufferedWriter bwriter = null ;

try{
  breader = new BufferedReader(new FileReader("env_table.txt")) ;
  String line = "" ;
  while((line = breader.readLine())!= null){
  String value ;
  String key ;
  int index ;
  index = line.indexOf("=") ;
  key = line.substring(0, index).trim() ;
  value = line.substring(index+1, line.length()).trim() ;
  setMap(key, value);
}

System.out.println("================");
System.out.println("Color:"+getMap("color"));

}catch (Exception e) {
  System.err.println(e.toString());
}finally{
  if(breader != null){
  breader.close();
  }
  if(bwriter != null){
  bwriter.close();
  }
}
}

private static void setMap(String key, String value){
map.put(key, value);
}

private static String getMap(String key){
return map.get(key).toString();
}
}

  • BufferedReader和BufferedWriter
利用FileReader或是FileInputStream 都是直接叫OS逐一字元的讀取外部IO的資料,這種方式會造成OS系統的繁忙使效能不佳,通常會利用會先將外部資料存放在記憶體中,也稱為緩衝區(buffered IO)。
   1. BufferedReader breader = new BufferedReader(new FileReader("reader.txt"))
   2. BuffertedWriteer bwriter = new BufferedWriter(new FileWriter("writer.txt"))
  • Data Stream
資料串流是以二進位檔讀取與寫入資料,基本資料型別(int, double, float, boolean...)和字串,需要將資料以二進制排好既可,DataInputStream和DataOutputStream物件都可以支援資料型態的轉換。


    Name: BinaryDatabase資料庫
    Desc : 有一份早餐清單可以提供客人去選取,內容名稱、價錢,但是可以隨意的更動名單內容, 
              利用二元進制檔來當作早餐清單內容。

      早餐清單
    id    item      price 
     1     milk       50.0
     2     water     10.0
     3     ham       5.0
     4     egg        8.0
    public class TestDataStream {

    public class Breakfast{
    private int id ;
    private String item ;
    private double price ;

    public Breakfast(int id, String item, double price){
    this.id = id ;
    this.item = item ;
    this.price = price ;
    }
    }

    public static void main(String[] args) throws IOException {

      TestDataStream tds = new TestDataStream() ;
      //定義早餐菜單
      List<Breakfast> breakfastList = new ArrayList<>() ;
      breakfastList.add(  tds.new Breakfast( 1, "milk", 50.0));
      breakfastList.add(  tds.new Breakfast( 2, "water", 10.0));
      breakfastList.add(  tds.new Breakfast( 3, "ham", 5.0));

        //寫入早餐明細
        DataInputStream dis =null ;
        DataOutputStream dos = null ;

    try{
     System.out.println("寫入早餐明細");
     dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream("breakfast.txt"))) ;

     for(int i=0 ; i< breakfastList.size() ;i++){
         Breakfast b = breakfastList.get(i) ;
        dos.writeInt(b.id);
        dos.writeUTF(b.item);
        dos.writeDouble(b.price);
     }

     //關閉文字檔
     dos.close();
     System.out.println("讀取資料");
      dis = new DataInputStream(new BufferedInputStream(new FileInputStream("breakfast.txt"))) ;
      System.out.format("%10s %10s %10s \n", "序號", "型號","價格");
      while(true){
      Breakfast b = tds.new Breakfast(dis.readInt(), dis.readUTF(), dis.readDouble()) ;
      System.out.format("%10d %10s %10f  \n", b.id, b.item , b.price );
      }
    }catch(IOException ioe){
        System.out.println(ioe.toString());
        ioe.printStackTrace();
    }finally{
      if(dos!=null){
      dos.close();
    }
        if(dos!=null){
        dis.close();
    }
    }
    }
    }


    Hot : 如果價格需要更高的精準度,需要定義BigDecimal的物件是否可以使用?
    • Object Streams
    主要的類別:ObjectOutputStream, ObjectInputStream
    主要支援物件的資料型態(Double、Bigdecimal...),但是要使用Object需要實做Serializable.

    NIO 

    現在我們討論一下何謂檔案系統,通常我們在儲存檔案時,是以階層是去存放檔案,那JAVA程式如何去知道目前的目錄的所在位置 ?
    • 了解檔案目錄結構
     每一個檔案系統都會有一個根目錄(root),在win系統下可能是C:\,linux系統下則為/ ,所以當要表達a.mp3的位置是" /音樂/a.mp3",但是如果子目錄太深每次這樣表示變成一件很繁瑣的事情,那要如何去解決這個問題? 答案: 相對路徑(Relative directory)



    • 相對路徑與絕對路徑(Relative or Absolute)
    絕對路徑就是都會以root目錄表示,
    相對路徑則會以目前的位置去表示該檔案的路徑,例如; 目前在音樂中,表達底下的音樂檔為
    a.mp3,要表達重要目錄下的檔案為"../重要/2013/01.txt"

    • 連結符號(Symbolic Links)
    在windows系統下有當你要進入快速其他資料夾,可以建立捷徑,表示它只是個連結並不有實際檔案的功能,只是方便進入其他目錄,這種連結符號在SE 7開始支援屬性的設定。

    • Path處理
    類別: Path
    Path類別使用在讀取目錄、目錄權限、轉換路徑等等的功能實現

    常用的功能 例子
    建立目錄或是檔案 Path p1 = Paths.get("/音樂/");
    Path p2 = Paths.get("/音樂/a.mp3");
    Path p3 = Paths.get(URI.create("file:///音樂"));

    取的目錄的相關資訊 Path path = Paths.get("C:\\音樂\\a.mp3");
    System.out.format("toString: %s%n", path.toString());
     System.out.format("getFileName: %s%n", path.getFileName()); System.out.format("getName(0): %s%n", path.getName(0)); System.out.format("getNameCount: %d%n", path.getNameCount()); System.out.format("subpath(0,2): %s%n", path.subpath(0,2)); System.out.format("getParent: %s%n", path.getParent()); System.out.format("getRoot: %s%n", path.getRoot());
    轉換網路目錄 Path p1 = Paths.get("C:\\Users");
     System.out.format("%s%n", p1.toUri());
    轉換為實體目錄 Path p1 = Paths.get("C:\\Users");
     System.out.println(p1.toRealPath());
    結合兩個目錄 Path p1 = Paths.get("C:\\Users");
    Path p2 = Paths.get("C:\\Users\\bryan");
    System.out.println(p1.resolve(p2));
    System.out.println(p1.resolve("Account"));
    結果:
    C:\Users\bryan
    C:\Users\Account
    Note:
    // Solaris syntax
          Path path = Paths.get("sally/bar");
     // Microsoft Windows syntax
         Path path = Paths.get("sally\\bar");

    *Glob
    *  符號表任何字串或是數字
    **  
    ? 任一字元
    {item1, item2, item3} 表示為多個字串
    [ ]  表示為一個區段,Ex: [0-9] 為0-9之間
      

    • File 檔案資訊
    File類別是用來讀取或是設定檔案資訊、目錄資訊等等,

    建構子

    Name Description
    File(File paraent, String fileName) 設定檔案名稱
    File(String pathname/path) 建立一個File實例,參數可以是檔案名稱或是路徑
    File(String path, String fileName) 第一個參數: 路徑字串 ,第二個參數:檔案字串 


    函式

    Name Description
    boolean createNewFile() 建立新檔
    static File createTempFile(String prefix, String suffix) 建立暫時檔
    static File createTempFile( String prefix, String suffix, File directory) 建立暫存檔,prefix: 檔名 , suffix:副檔名;directory:目錄
    boolean mkdir() 建立目錄
    boolean mkdirs() 建立目錄                      
    boolean exists() 檔案是否存在
    boolean renameTo( File file) 更改檔案名稱
    boolean delete() 刪除檔案
    boolean isAbsolute() 是否絕對路徑
    boolean isDirectory() 是否為目錄
    boolean isFile() 是否為檔案
    boolean isHidden() 是否為隱藏檔
    boolean isRead() 是否可讀
    boolean isWrite() 是否可寫
    String getName() 取得檔案名稱
    String  getAbsoluteFile() 取得檔案絕對路徑
    String  getAbsolutePath() 取得檔案絕對路徑
    String getPath() 取得路徑
    String getParent() 取得上層路徑
    Long length() 檔案大小
    String[] list() 回傳所有的目錄下的檔案或是目錄
    File listFiles() 回傳所有的目錄下的檔案
    long lastModified() 回傳最後修改時間



























































    2013年10月9日

    JAVA 集合架構與泛型

    集合架構與泛型


    • 集合

    當我們使用陣列時,作大量資料的變動會需要做很多不必要的運算動作。所以JAVA設計集合的資料結構去做這些物件大量的變更。在集合的操作上,會將型別轉為Object存入集合中。

    (1)集合繼承關係



    (2) Collection方法
    用來對集合的物件的基本操作

    Name Description
    boolean add(E e)  將物件加入到目前集合中
    boolean  addAll(Collection<? extends E> c)  將集合物件加入到目前集合中
    void clear()  移除所有的集合元素
    boolean contains(Object o)  如果集合有符合o元素回傳true,否回傳false
    boolean containsAll(Collection<?> c)  如果該集合有符合傳入集合所有的元素者回傳true,否回傳false
    boolean equals(Object o)  比較物件是否相等
    int hashCode()  回傳 hash code 
    boolean isEmpty()  如果該集合沒有任何物件回傳true
     Iterator<Eiterator()  回傳iterator物件集合,可以使用iterator的物件方法
    boolean  remove(Object o)  從目前物件集合移除符合傳入的物件
    boolean   removeAll(Collection<?> c)  從目前物件集合移除符合傳入的物件
    int size()  傳回此集合所有元素的個數
    Object[] toArray()   回傳陣列物件
    <T> T[] 
    toArray(T[] a)
     
    回傳陣列物件                      

    程式
    /*****************************************************************************************************************
    *   name : List 範例
    *   description: 實作add, isEmpty, remove, size, iterator方法
    *   author : Bryant
    *****************************************************************************************************************/
    import java.util.Iterator;
    import java.util.LinkedList;
    import java.util.List;

    public class Product {

    public String name ;
    public String id ; 
    public  Double price ; 

    public Product(String name, String id, Double price){
    this.name = name ; 
    this.id = id ; 
    this.price = price ;
    }
    @Override
    public String toString() {
    // TODO Auto-generated method stub
    return "id:" + this.id + "\t name:"+this.name +"\t price:" + this.price +"\t\n"  ;
    }

    public static void main(String[] args) {
    // TODO Auto-generated method stub

    List<Product> list = new LinkedList<Product>() ;
    System.out.println("判斷是否為空物件:"+ list.isEmpty());

    Product p1 = new Product("ipad", "K001",  299d) ; 
    Product p2 = new Product("iphone", "K101",  299d); 
    Product p3 = new Product("ipod", "K002",  299d); 
    Product p4 = new Product("imac", "K015",  500d); 
    list.add(p1) ;
    list.add(p2) ;
    list.add(p3) ;
    list.add(p4) ;

    System.out.println("加入ipad, iphone的產品資料:\n" + list.toString());
    System.out.println("產品總計:"+list.size());

    //移除資料例子
    if(list.remove(p1)){
    System.out.println("移除ipad的產品資料:"+ p1);
    }else{
    System.out.println("資料庫沒有資料");
    }

    System.out.println("目前的資料:\n" + list.toString());

    //使用iterator
    System.out.println("使用iterator集合走訪集合:");
    Iterator<Product> it = list.iterator();
    while(it.hasNext()){
    System.out.println(it.next()); //取出元素
    }

    }

    }
    • Iterator 介面
    Name Description
    boolean hasNext() 是否有下一個元素,若有回傳true
    Obejct next() 回傳下一個Object元素並指定下一個元素
    void remove() 移除目前的元素
    • Enumeration介面
    Name Description
    boolean  hasMoreElements() 是否有下一個Enumeration元素
    Object nextElement() 回傳下一個Object元素並指定下一個元素
    • Set 介面
    set介面是繼承Collection介面,set再加入元素時,會利用equal()方法來判斷加入元素內容使否重複,所以set不可以重複。實作: LinkedHashSet, HashSet, TreeSet

    public interface Set extends Collection

    (1) HashSet
    HashSet元素不允許重複,利用hashCode()來當作 index-value,

    /*****************************************************************************************************************
    *   name : HashSet範例
    *   description: 實作當我們建立重複的字串物件,結果hashSet不允許重複的元素
    *   author : Bryant
    *****************************************************************************************************************/
    public static void main(String[] args) {
    // HashSet 不允許重複的元素

    HashSet<String> hset = new HashSet<String>() ; 
    hset.add(new String("AAA")) ;
    hset.add(new String("BBB")) ;
    hset.add(new String("AAA")) ;
    hset.add(new String("AAA")) ;

    System.out.println("HashSet元素:");
    for(String p : hset){
    System.out.println(p);

    }
    Result:
    HashSet元素:
    BBB
    AAA

    (2) LinkedHashSet類別
    它是利用資料結構的doubly-linked相互連結,利用next、previous節點指向其他元素,它具有順序性。

    /*****************************************************************************************************************
    *   name : 
    LinkedHashSet範例
    *   description: 建立雙鏈結的集合
    *   author : Bryant
    *****************************************************************************************************************/
    public static void main(String[] args) {

    System.out.println("LinkedHashSet元素:");
    LinkedHashSet<Product> lhset = new LinkedHashSet<Product>() ; 
    lhset.add(new Product("ipad", "A001", 299.0)) ;
    lhset.add(new Product("imac", "A101", 499.0)) ;
    lhset.add(new Product("ipod", "A021", 100.0)) ;
     
    for(Product p : lhset){
    System.out.println(p);

    }
    }

    (3) SortedSet介面
    利用紅黑數的資料結構來實作,
    /*****************************************************************************************************************
    *   name : 
    SortedSet範例
    *   description: 建立TreeSet具有排序性
    *   author : Bryant
    *****************************************************************************************************************/
    public static void main(String[] args) {

    //SortedSet 搜尋件
    System.out.println("SortedSet元素:");
    TreeSet<String> sts = new TreeSet<String>() ; 
    sts.add("A") ; 
    sts.add("F") ; 
    sts.add("B") ; 
    sts.add("E") ; 
    Iterator<String> it = sts.iterator();
    while(it.hasNext()){
    System.out.println(it.next());
    }
    }

    • List介面
    List集合使用的方式相似陣列的使用方式,利用索引來找到該元素。它也是繼承collection介面,所以可以利用Collections的類別來做操作。

    Name Description
    boolean add(E e)  將物件加入到目前集合中
    boolean  addAll(Collection<? extends E> c)  將集合物件加入到目前集合中
    Object get(int index) 利用索引取出物件
    int indexOf(Object o) 回傳物件的索引值,如果沒有找到回傳-1,否則回傳該物件的索引值
    Object remove(int index) 回傳被移除的物件

    List<E> subList(int from, int to)
    回傳子List                     

    (1)ArrayList

    /*****************************************************************************************************************
    *   name : List 範例
    *   description: 實作List方法
    *   author : Bryant
    *****************************************************************************************************************/
    public static void main(String[] args) {
    // TODO Auto-generated method stub

    ArrayList<Product> aList = new ArrayList<Product>() ; 
    aList.add(new Product("ipad", "A001", 299.0)) ;
    aList.add(new Product("imac", "A101", 499.0)) ;
    aList.add(new Product("ipod", "A021", 100.0)) ;

    System.out.println("元素列表:");
    for(int i=0 ; i < aList.size();i++){
    System.out.println(aList.get(i));
    }

    int index = aList.indexOf(aList.get(1));
    System.out.println("imac index:"+index);

    aList.remove(aList.get(1));

    System.out.println("元素列表:");
    for(int i=0 ; i < aList.size();i++){
    System.out.println(aList.get(i));
    }

    }


    (2) Vector
    當你需要考慮到資料需要做同步時,我們可以利用Vector作物件的集合。

    /*****************************************************************************************************************
    *   name : Vector 範例
    *   description: 實作vector
    *   author : Bryant
    *****************************************************************************************************************/
    public static void main(String[] args) {
    //Vector
    System.out.println("建立Vector集合:");
    Vector<String> vec = new Vector<String>() ; 
    vec.add("Jack") ; 
    vec.add("Bryant") ; 
    vec.add("VIVI");

    Iterator<String> it = vec.iterator() ; 
    while(it.hasNext()){
    System.out.println(it.next());
    }
    }


    • Queue

    Queue是一種先進先出(FIFO, first-in-first-out)的集合,利用offer()和poll()兩個方法

    Name Description
    boolean offer(E e) 加入一個特定的物件,成功為true,否為false
    E peek() 依序取出元素,但不移除該元素,當為空物件,回傳null
    E element() 依序取出元素
    E poll() 依序取出元素
    E remove() 移除元素                     

    /*****************************************************************************************************************
    *   name : Queue範例
    *   description: Queue的走訪實作
    *   author : Bryant
    *****************************************************************************************************************/
    public static void main(String[] args) {
    Queue<String> loginSequence = new LinkedList<String>();
     loginSequence.add("Jack");
     loginSequence.add("Hask");
     loginSequence.add("Lkk");
     loginSequence.add("Lennon");
     System.out.println("The login sequence is: " + loginSequence);
     
     while(!loginSequence.isEmpty())
         System.out.println( loginSequence.poll());
      }

    }


    • Map介面
    Map是一種key-value的方式去儲存物件集合,但是key不可重複,Map: Hashtable, HashMap

    Name Description
    boolean add(E e)  將物件加入到目前集合中
    boolean  addAll(Collection<? extends E> c)  將集合物件加入到目前集合中
    Object get(int index) 利用索引取出物件
    int indexOf(Object o) 回傳物件的索引值,如果沒有找到回傳-1,否則回傳該物件的索引值
    Object remove(int index) 回傳被移除的物件

    List<E> subList(int from, int to)
    回傳子List                     



    (1)Hashtable
    Hashtable的鍵與值不得置入null。
    /*****************************************************************************************************************
      name : Hashtable範例
    *   description: 實作
    Hashtable,且鍵為null時
    *   author : Bryant

    *****************************************************************************************************************/
    public static void main(String[] args) {
    // Hashtable
    Hashtable<String, String> htable = new Hashtable<>();
    htable.put("K01", "ASUS") ;
    htable.put(null, "ACER") ;
    htable.put("K02", "APPLE") ;
    htable.put("K04", "HP") ;
       System.out.println("電腦品牌:");
    System.out.println("K01 =>" + hmap.get("K01"));
    System.out.println("K01 =>" + hmap.get("K02"));

    }

    結果:

    Exception in thread "main" java.lang.NullPointerException
    at java.util.Hashtable.hash(Unknown Source)
    at java.util.Hashtable.put(Unknown Source)

    at Example.MapEx.main(MapEx.java:25)



    (2)HashMap
    hashmap可以容許鍵或值是null,它是一種thread-safe

    /*****************************************************************************************************************
    *   name : 
    HashMap範例
    *   description: 實作HashMap,且鍵為null時
    *   author : Bryant

    *****************************************************************************************************************/
    public static void main(String[] args) {
    HashMap hmap = new HashMap<>(); hmap.put("K01", "ASUS") ; hmap.put("K02", "ACER") ; hmap.put("K03", "APPLE") ; hmap.put("K03", "HP") ; //會蓋掉前面的值 hmap.put(null, "ACER") ; System.out.println(hmap.toString()); System.out.println("K01 =>" + hmap.get("K01")); System.out.println("K01 =>" + hmap.get(null));
    }

    結果:
    {null=ACER, K03=HP, K02=ACER, K01=ASUS}
    K01 =>ASUS
    K01 =>ACER

    (3) LinkedMap
    LinkedMap會依照次序將元素加入集合中,

    /*****************************************************************************************************************
    *   name : 
    LinkedMap範例
    *   description: 
     實作LinkedMap,且鍵為null時

    *   author : Bryant

    *****************************************************************************************************************/
    public static void main(String[] args) {
    //LinkedHashMap
    LinkedHashMap<String, Product[]> linkedMap = new LinkedHashMap<String,Product[]>() ;

    Product p1 = new Product("ipad", "K001",  299d) ; 
    Product p2 = new Product("iphone", "K101",  199d); 
    Product p3 = new Product("ipod", "K002",  399d); 
    Product p4 = new Product("imac", "K015",  500d); 
    Product[] group1 = {p1, p2} ; 
    Product[] group2 = {p3, p4} ; 

    linkedMap.put("建國路分店", group1) ;
    linkedMap.put("中正路分店", group2) ;
    System.out.println("建國路分店 =>" +  Arrays.toString(linkedMap.get("建國路分店")));
    System.out.println("中正路分店 =>" +  Arrays.toString(linkedMap.get("中正路分店")));
    }

    (4) SortedMap介面
    TreeMap實作SortedMap具有排序性

    /*****************************************************************************************************************
    *   name : 
    SortedMap範例
    *   description: 實作TreeMap依靠鍵值作排序
    *   author : Bryant
    *****************************************************************************************************************/
    public static void main(String[] args) {
    // SortedMap
    TreeMap<Integer, String> treeMap = new TreeMap<Integer, String>() ; 
    treeMap.put(1, "Jack");
    treeMap.put(6, "Vivi");
    treeMap.put(2, "Jock");
    treeMap.put(5, "Blackhaker");
    System.out.println("SortedMap : ");
    System.out.println(treeMap.toString());

    }

    結果:
    SortedMap : 

    {1=Jack, 2=Jock, 5=Blackhaker, 6=Vivi}


    • Comparable and Comparator Interfaces
    Compareable和Comparator介面常用來比較相似的物件,例如當我有一組的產品的物件,你如何去比較這些產品物件。

    int compareTo(Element that)
    return 1 if current object > passed object
    return 0 if current object == passed object
    return -1 if current object < passed object

    (1) 實作Comparable
    在實作Comparable時,必須要override compareTo的方法,

    /*****************************************************************************************************************
    *   name : 
    Comparable範例
    *   description: 實作產品排序由大到小
    *   author : Bryant
    *****************************************************************************************************************/
    public class Product implements Comparable<Product>{
    public String name ;
    public String id ; 
    public  Double price ; 

    public Product(String name, String id, Double price){
    this.name = name ; 
    this.id = id ; 
    this.price = price ;
    }

    @Override
    public String toString() {
    // TODO Auto-generated method stub
    return "id:" + this.id + "\t name:"+this.name +"\t price:" + this.price +"\t\n"  ;
    }

    public static void main(String[] args) {

    List<Product> list = new LinkedList<Product>() ;
    Product p1 = new Product("ipad", "K001",  299d) ; 
    Product p2 = new Product("iphone", "K101",  299d); 
    Product p3 = new Product("ipod", "K002",  299d); 
    Product p4 = new Product("imac", "K015",  500d); 
    list.add(p1) ;
    list.add(p2) ;
    list.add(p3) ;
    list.add(p4) ;

    Iterator<Product> it = list.iterator();
    while(it.hasNext()){
    System.out.println(it.next()); //取出元素
    }

    System.out.println("排序後的物件");
    TreeSet<Product> tree = new TreeSet<>(list) ; 
     it = tree.iterator();
    while(it.hasNext()){
    System.out.println(it.next()); //取出元素
    }
    }

    @Override
    public int compareTo(Product that) {
    // TODO Auto-generated method stub
    if(this.id.compareTo(that.id)>=1)
    return -1;
    else if(this.id.compareTo(that.id)==0)
    return 0 ; 
    else
    return 1 ;
    }
    }


    (2)實作Comparator
    如果你不想要更改Product物件的比較方式,你可以實作comparator的方式去實作排序。


    /*****************************************************************************************************************
    *   name : Comparator
    範例
    *   description: 建立排序產品價錢有小到大
    *   author : Bryant
    *****************************************************************************************************************/
    public class ProdcutComparator implements Comparator<Product>{


    @Override
    public int compare(Product o1, Product o2) {
    // TODO Auto-generated method stub
    return o1.price.compareTo(o2.price);
    }
    }  

    /*****************************************************************************************************************
    *   name : 
    Comparator範例
    *   description: 
     建立排序產品價錢有小到大
    *   author : Bryant
    *****************************************************************************************************************/
    public class Product implements Comparable<Product>{

    public String name ;
    public String id ; 
    public  Double price ; 
    public Product(String name, String id, Double price){
    this.name = name ; 
    this.id = id ; 
    this.price = price ;
    }

    @Override
    public String toString() {
    // TODO Auto-generated method stub
    return "id:" + this.id + "\t name:"+this.name +"\t price:" + this.price +"\t\n"  ;
    }

    public static void main(String[] args) {

    List<Product> list = new LinkedList<Product>() ;
    Product p1 = new Product("ipad", "K001",  299d) ; 
    Product p2 = new Product("iphone", "K101",  199d); 
    Product p3 = new Product("ipod", "K002",  399d); 
    Product p4 = new Product("imac", "K015",  500d); 
    list.add(p1) ;
    list.add(p2) ;
    list.add(p3) ;
    list.add(p4) ;

    Iterator<Product> it = list.iterator();
    while(it.hasNext()){
    System.out.println(it.next()); //取出元素
    }

    System.out.println("排序後的物件");
    Collections.sort(list, new ProdcutComparator());
    it = list.iterator();
    while(it.hasNext()){
    System.out.println(it.next()); //取出元素
    }
    }

    @Override
    public int compareTo(Product that) {
    // TODO Auto-generated method stub
    if(this.id.compareTo(that.id)>=1)
    return -1;
    else if(this.id.compareTo(that.id)==0)
    return 0 ; 
    else
    return 1 ;
    }
    }
    結果:
    id:K001 name:ipad price:299.0

    id:K101 name:iphone price:199.0

    id:K002 name:ipod price:399.0

    id:K015 name:imac price:500.0

    排序後的物件
    id:K101 name:iphone price:199.0

    id:K001 name:ipad price:299.0

    id:K002 name:ipod price:399.0

    id:K015 name:imac price:500.0



    (3)比較
    Comparable Comparator
    通常會使用預設的比較方式 實作自訂的比較方式
    實作Comparable方法,不需要跟物件類別分開 實作d


    • Collections類別
    Collections為公用函式,收集在java.lang.Object,可作為集合資料的處理。

    Name Description
    boolean addAll( Collection <? super T> c, T elements) 加入集合
    Queue asLifoQueue(Deque<T> deque) 回傳Deque集合
    int binarySearch(List<? extends Comparable<? super T>> list, T key) 搜尋串列回傳符合該物件的位置
    int binarySearch(List<? extends Comparable<? super T>> list, T key,Comparator<? super T> c ) 搜尋串列回傳符合該物件的位置,第三個參數可以使用自定排序方法
    List<E> checkedList(List<E> list, Class<E> type) 傳回隨機的Map集合
    Map<K,V> checkedMap(Map<K,V> m, Class<K> keyType, Class<V> valueType) 傳回隨機的List集合
    Set<E>checkedSet(Set<E> s, Class<E> type) 傳回隨機的Set集合
    SortedMap<K,V>
      checkedSortedMap(SortedMap<K,V> m, Class<K> keyType, Class<V> valueType) 
    傳回隨機的SortedMap集合
    void copy(List<? super T> dest, List<? extends T> src) 複製List另一個List集合
    Enumeration<T>  enumeration(Collection<T> c)  回傳enumeration
    ArrayList<T> list(Enumeration<T> e)  回傳一個ArrayList集合
    max(Collection<? extends T> coll) 找出最大值
    max(Collection<? extends T> coll, Comparator<? super T> comp) 找出最大值,第二個參數可以使用自定排序方法
    min(Collection<? extends T> coll) 找出最小值
    min(Collection<? extends T> coll, Comparator<? super T> comp) 找出最小值,第二個參數可以使用自定排序方法
    static void reverse(List<?> list)  反向排序
    static void shuffle(List<?> list)  亂數排序
    void sort(List<T> list)  排序
    void sort(List<T> list, Comparator<? super T> c)                        
    • Arrays 類別








    • Generics 泛型
    (1) 基本泛型概念

    Java 5.0 所提供的泛型是指廣泛的使用型別,在5.0之前通常會用Object來解決需要泛型的實作,會用到泛型來解決問題,通常是一個邏輯或是程序相同,只是資料型態不同而已,在5.0之前可以利用Object來解決這個問題或是利用泛型不需要因為資料型態不同而去實作很多的類別檔案出來

    /*****************************************************************************************************************
    *   name : Object範例
    *   description: 使用Object來當作泛行使用
    *   author : Bryant
    *****************************************************************************************************************/
    public class Operator {

    private Object obj ;
    public void setObj(Object obj){
    this.obj  = obj;
    }
    public Object getobj(){
    return this.obj ;
    }

    public static void main(String[] args) {

    Operator op1 = new Operator() ; 
    Operator op2 = new Operator() ; 
    op1.setObj(10);
    op2.setObj(20f); 
    Integer i1 = (Integer)op1.getobj() ; 
    Integer i2 = (Integer)op2.getobj() ;    //出現錯誤,因為20f為浮點數
    Integer sum = i1 + i2 ;
    System.out.println("sum:"+sum);

    }
    }
    Exception in thread "main" java.lang.ClassCastException: java.lang.Float cannot be cast to java.lang.Integer
    at Example.Operator.main(Operator.java:21)

    /*****************************************************************************************************************
    *   name : 泛型
    *   description: 實作泛型
    *   author : Bryant
    *****************************************************************************************************************/
    public class Pair<T1, T2> {
    T1 obj1;
    T2 obj2;
    Pair(T1 one, T2 two) {
    obj1 = one;
    obj2 = two;
     }

    public T1 getFirst() {
          return obj1;
    }

    public T2 getSecond() {
          return obj2;
     }

    public static void main(String[] args) {
    Pair<Integer, Integer> pair = new Pair<Integer, Integer>(100, 100);
    Integer sum = pair.getFirst() + pair.getSecond();
    System.out.println("Sum:"+sum);

    }
    }

    Ex :
    哪幾種在編譯上或執行上不會出現error
    1. List<Integer> intList = new List<Integer>();
    2. List<Integer> intList = new ArrayList<Integer>();  (O)
    3. List<Number> intList = new ArrayList<Integer>();
    4. List<Integer> intList = new ArrayList<Number>();

    (2)Diamond 鑽石
     1. List<Integer> intList = new ArrayList<Integer>(); 
     2. List<Integer> intList = new ArrayList<>();  //JAVA 7.0新增Diamond的寫法,
    第一個和第二個是相同的,Diamond寫法編譯器會將左邊的型別自動去推算右邊的型別。

    Ex: 下列宣告的效果都是一樣
         List<Integer> intList = new ArrayList<Integer>(); 
         List<Integer> intList = new ArrayList<>(); 
         List<Integer> intList = new ArrayList(); 


    (3) 泛型的限制
    1. 泛型不可以接受基本型別的宣告(int, double, float....)
    2. Iterator 支援泛型結構
    3. 使用<?>來完成萬用泛型, List<Object> 跟 List<?>不太一樣,List<?>是任何List的supertype 

    泛型的資料型態Autoboxing/Unboxing
    /*****************************************************************************************************************
    *   name : 泛型範例
    *   description:  Autoboxing 和 Unboxing
    *   author : Bryant
    *****************************************************************************************************************/
    public static void main(String[] args) {
    // TODO Auto-generated method stub
    Vector<Integer> vec = new Vector() ;
    vec.add(200) ; //自動封裝為Integer
    vec.add(500) ; // 自動封裝為Integer

    for( int i : vec){  // Unboxing
    System.out.println(" number: "+i);
    }
    }