<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    licheng700

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      26 Posts :: 5 Stories :: 5 Comments :: 1 Trackbacks

    #

    世界上的各地區都有本地的語言。地區差異直接導致了語言環境的差異。在開發一個國際化程序的過程中,處理語言問題就顯得很重要了。

      這是一個世界范圍內都存在的
    問題,所以,Java提供了世界性的解決方法。本文描述的方法是用于處理中文的,但是,推而廣之,對于處理世界上其它國家和地區的語言同樣適用。

      漢字是雙字節的。所謂雙字節是指一個雙字要占用兩個BYTE的位置(即16位),分別稱為高位和低位。中國規定的漢字編碼為GB2312,這是強制性的,目前幾乎所有的能處理中文的應用程序都支持GB2312。GB2312包括了一二級漢字和9區符號,高位從0xa1到0xfe,低位也是從0xa1到0xfe,其中,漢字的編碼范圍為0xb0a1到0xf7fe。

      另外有一種編碼,叫做GBK,但這是一份規范,不是強制的。GBK提供了20902個漢字,它兼容GB2312,編碼范圍為0x8140到0xfefe。GBK中的所有字符都可以一一映射到Unicode 2.0。

      在不久的將來,中國會頒布另一種標準:GB18030-2000(GBK2K)。它收錄了藏、蒙等少數民族的字型,從根本上解決了字位不足的問題。注意:它不再是定長的。其二字節部份與GBK兼容,四字節部分是擴充的字符、字形。它的首字節和第三字節從0x81到0xfe,二字節和第四字節從0x30到0x39。

      本文不打算介紹Unicode,有興趣的可以瀏覽“http://www.unicode.org/”查看更多的信息。Unicode有一個特性:它包括了世界上所有的字符字形。所以,各個地區的語言都可以建立與Unicode的映射關系,而Java正是利用了這一點以達到異種語言之間的轉換。

      在JDK中,與中文相關的編碼有:

      表1 JDK中與中文相關的編碼列表

    編碼名稱 說明
    ASCII 7位,與ascii7相同
    ISO8859-1 8-位,與 8859_1,ISO-8859-1,ISO_8859-1,latin1...等相同
    GB2312-80 16位,與gb2312,gb2312-1980,EUC_CN,euccn,1381,Cp1381, 1383, Cp1383, ISO2022CN,ISO2022CN_GB...等相同
    GBK 與MS936相同,注意:區分大小寫
    UTF8 與UTF-8相同
    GB18030 與cp1392、1392相同,目前支持的JDK很少

      在實際編程時,接觸得比較多的是GB2312(GBK)和ISO8859-1。

      為什么會有“?”號

      上文說過,異種語言之間的轉換是通過Unicode來完成的。假設有兩種不同的語言A和B,轉換的步驟為:先把A轉化為Unicode,再把Unicode轉化為B。

      舉例說明。有GB2312中有一個漢字“李”,其編碼為“C0EE”,欲轉化為ISO8859-1編碼。步驟為:先把“李”字轉化為Unicode,得到“674E”,再把“674E”轉化為ISO8859-1字符。當然,這個映射不會成功,因為ISO8859-1中根本就沒有與“674E”對應的字符。

      當映射不成功時,問題就發生了!當從某語言向Unicode轉化時,如果在某語言中沒有該字符,得到的將是Unicode的代碼“\uffffd”(“\u”表示是Unicode編碼,)。而從Unicode向某語言轉化時,如果某語言沒有對應的字符,則得到的是“0x3f”(“?”)。這就是“?”的由來。

      例如:把字符流buf =“0x80 0x40 0xb0 0xa1”進行new String(buf, "gb2312")操作,得到的結果是“\ufffd\u554a”,再println出來,得到的結果將是“?啊”,因為“0x80 0x40”是GBK中的字符,在GB2312中沒有。

      再如,把字符串String="\u00d6\u00ec\u00e9\u0046\u00bb\u00f9"進行new String (buf.getBytes("GBK"))操作,得到的結果是“3fa8aca8a6463fa8b4”,其中,“\u00d6”在“GBK”中沒有對應的字符,得到“3f”,“\u00ec”對應著“a8ac”,“\u00e9”對應著“a8a6”,“0046”對應著“46”(因為這是ASCII字符),“\u00bb”沒找到,得到“3f”,最后,“\u00f9”對應著“a8b4”。把這個字符串println一下,得到的結果是“?ìéF?ù”。看到沒?這里并不全是問號,因為GBK與Unicode映射的內容中除了漢字外還有字符,本例就是最好的明證。

      所以,在漢字轉碼時,如果發生錯亂,得到的不一定都是問號噢!不過,錯了終究是錯了,50步和100步并沒有質的差別。

      或者會問:如果源字符集中有,而Unicode中沒有,結果會如何?回答是不知道。因為我手頭沒有能做這個測試的源字符集。但有一點是肯定的,那就是源字符集不夠規范。在Java中,如果發生這種情況,是會拋出異常的。
    posted @ 2005-08-13 15:20 小海船 閱讀(106) | 評論 (0)編輯 收藏

    本文章以 UTF-8 為例,傳統的做法是用:

    String keyword 
     = new String(request.getParameter("keyword").getBytes("iso-8859-1"),"utf-8");
    

    如果用 Tomcat 5.0.1.6 以上的版本是最好處理的,直接改 server.xml ,找到 Connector 加上紅字的部份就可以了。

    <Connector port="8088"  maxThreads="150" 
    minSpareThreads="25" maxSpareThreads="75" 
    enableLookups="false" redirectPort="8443" 
    acceptCount="100" debug="0" connectionTimeout="20000"
    disableUploadTimeout="true" URIEncoding="UTF-8"  />
    

    另外如果要從 JSP 丟出一個 URL 的中文參數值,最好是用 URLEncode 的方式比較能確保的資料是正確的。

    範例:

    <a href=seach.jsp?keyword=<%= java.net.URLEncoder.encode(keyword,"UTF-8") %>>
    再搜尋
    </a>
    
    posted @ 2005-08-08 10:10 小海船 閱讀(131) | 評論 (0)編輯 收藏

    package dateandtime;

    import java.sql.Time;
    import java.text.ParseException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.Locale;

    public class SqlDateAndUtilDate {

     public static void main(String[] args) throws ParseException
     {
      java.sql.Date sqlDate=null;
      Date utilDate=null;
      utilDate= new Date(System.currentTimeMillis());
      System.out.println("utileDate="+utilDate);
      sqlDate=new java.sql.Date(System.currentTimeMillis());
      System.out.println("sqlDate="+sqlDate);
      System.out.println("sqlDateConvertoUtilDate="+((Date)sqlDate));
      Time sqlTime = new java.sql.Time(utilDate.getTime());
      System.out.println("sqlTime="+sqlTime);
            java.sql.Timestamp sqlTimestamp = new java.sql.Timestamp(utilDate.getTime());
            System.out.println("sqlTimestamp="+sqlTimestamp);
            String dataTime="3/Jun/2005 02:12:10 AM";
            SimpleDateFormat format = new SimpleDateFormat(
                    "dd/MMM/yyyy hh:mm:ss a", Locale.ENGLISH);
            Date date=format.parse(dataTime);
            System.out.println(date);
            /*format=new  SimpleDateFormat(
                    "yyyy-MMM-dd hh:mm:ss", Locale.ENGLISH);*/
            format.applyPattern("yyyy-MMM-dd hh:mm:ss");
            String dateString="2005-Aug-04 11:06:00";
            date=format.parse(dateString);
            System.out.println(date);
     }
    }


    package dateandtime;

    //日期和時間處理示例

    import java.util.*;
    import java.text.SimpleDateFormat;
    import java.sql.Date;
    import java.sql.Time;
    import java.sql.Timestamp;

    public class TestDateTime
    {
        public static void main(String[] argv)
        {
            long nCurrentTime = System.currentTimeMillis();
            java.util.Date utilDate = new java.util.Date(nCurrentTime);

            //以下是用于數據庫操作的日期和時間類
            java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());  //java.util.Date和java.sql.Date的轉換
            java.sql.Time sqlTime = new java.sql.Time(utilDate.getTime());
            java.sql.Timestamp sqlTimestamp = new java.sql.Timestamp(nCurrentTime);

            //Calendar用于獲取指定的時間項(字段)
            Calendar calendar = Calendar.getInstance();
            calendar.setTimeInMillis(nCurrentTime);

            int year = calendar.get(Calendar.YEAR);
            int month = calendar.get(Calendar.MONTH) + 1;   //注意:返回的月份是基于0的!
            int day = calendar.get(Calendar.DAY_OF_MONTH);
            int hour = calendar.get(Calendar.HOUR_OF_DAY);
            int minute = calendar.get(Calendar.MINUTE);
            int second = calendar.get(Calendar.SECOND);

            System.out.println("Current date is: " + year + "年" + month + "月" + day + "日");
            System.out.println("Current time is: " + hour + "時" + minute + "分" + second + "秒");

            //SimpleDateFormat用于格式化日期和時間
            SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String szDatetime1 = df.format(utilDate);
            System.out.println("Current datetime is: " + szDatetime1);

            //以下計算兩個日期值之間相差的時間
            java.util.Date date2 = new java.util.Date(nCurrentTime - 24600 * 1000);

            long nMilliSeconds = utilDate.getTime() - date2.getTime();
            long nSeconds =  nMilliSeconds / 1000;  //把毫秒換算成秒
            double nDays = nSeconds / (24d * 60d * 60d);  //把秒換算成天

            String szDatetime2 = df.format(date2);
            System.out.println("Time between " + szDatetime1 + " and " + szDatetime2 + " is " + nSeconds + " seconds (" + nDays + " days)");
        }
    }


     

    posted @ 2005-08-04 11:27 小海船 閱讀(826) | 評論 (0)編輯 收藏

    第一,final, finally, finalize的區別.

    final 修飾符(關鍵字)如果一個類被聲明為final,意味著它不能再派生出新的子類,不能作為父類被繼承。因此一個類不能既被聲明為 abstract的,又被聲明為final的。將變量或方法聲明為final,可以保證它們在使用中不被改變。被聲明為final的變量必須在聲明時給定初值,而在以后的引用中只能讀取,不可修改。被聲明為final的方法也同樣只能使用,不能重載

    finally 再異常處理時提供 finally 塊來執行任何清除操作。如果拋出一個異常,那么相匹配的 catch 子句就會執行,然后控制就會進入 finally 塊(如果有的話)。
    finalize 方法名。Java 技術允許使用 finalize() 方法在垃圾收集器將對象從內存中清除出去之前做必要的清理工作。這個方法是由垃圾收集器在確定這個對象沒有被引用時對這個對象調用的。它是在 Object 類中定義的,因此所有的類都繼承了它。子類覆蓋 finalize() 方法以整理系統資源或者執行其他清理工作。finalize() 方法是在垃圾收集器刪除對象之前對這個對象調用的。

    第二,Anonymous Inner Class (匿名內部類) 是否可以extends(繼承)其它類,是否可以implements(實現)interface(接口)?

    匿名的內部類是沒有名字的內部類。不能extends(繼承) 其它類,但一個內部類可以作為一個接口,由另一個內部類實現。

    第三,Static Nested Class 和 Inner Class的不同,說得越多越好Nested Class (一般是C++的說法),Inner Class (一般是JAVA的說法)。Java內部類與C++嵌套類最大的不同就在于是否有指向外部的引用上。具體可見http: //www.frontfree.net/articles/services/view.asp?id=704&page=1
    注: 靜態內部類(Inner Class)意味著1創建一個static內部類的對象,不需要一個外部類對象,2不能從一個static內部類的一個對象訪問一個外部類對象

    第四,&和&&的區別。
    &是位運算符。&&是布爾邏輯運算符。

    第五,HashMap和Hashtable的區別。

    都屬于Map接口的類,實現了將惟一鍵映射到特定的值上。
    HashMap 類沒有分類或者排序。它允許一個 null 鍵和多個 null 值。
    Hashtable 類似于 HashMap,但是不允許 null 鍵和 null 值。它也比 HashMap 慢,因為它是同步的。

    第六,Collection 和 Collections的區別。
    Collections是個java.util下的類,它包含有各種有關集合操作的靜態方法。
    Collection是個java.util下的接口,它是各種集合結構的父接口。

    第七,什么時候用assert。
    斷言是一個包含布爾表達式的語句,在執行這個語句時假定該表達式為 true。如果表達式計算為 false,那么系統會報告一個 Assertionerror。它用于調試目的:
    assert(a > 0); // throws an Assertionerror if a <= 0
    斷言可以有兩種形式:
    assert _Expression1 ;
    assert _Expression1 : _Expression2 ;
    _Expression1 應該總是產生一個布爾值。
    _Expression2 可以是得出一個值的任意表達式。這個值用于生成顯示更多調試信息的 String 消息。
    斷言在默認情況下是禁用的。要在編譯時啟用斷言,需要使用 source 1.4 標記:
    javac -source 1.4 Test.java
    要在運行時啟用斷言,可使用 -enableassertions 或者 -ea 標記。
    要在運行時選擇禁用斷言,可使用 -da 或者 -disableassertions 標記。
    要系統類中啟用斷言,可使用 -esa 或者 -dsa 標記。還可以在包的基礎上啟用或者禁用斷言。
    可以在預計正常情況下不會到達的任何位置上放置斷言。斷言可以用于驗證傳遞給私有方法的參數。不過,斷言不應該用于驗證傳遞給公有方法的參數,因為不管是否啟用了斷言,公有方法都必須檢查其參數。不過,既可以在公有方法中,也可以在非公有方法中利用斷言測試后置條件。另外,斷言不應該以任何方式改變程序的狀態。

    第八,GC是什么? 為什么要有GC? (基礎)。

    GC是垃圾收集器。Java 程序員不用擔心內存管理,因為垃圾收集器會自動進行管理。要請求垃圾收集,可以調用下面的方法之一:
    System.gc()
    Runtime.getRuntime().gc()

    第九,String s = new String("xyz");創建了幾個String Object?

    兩個對象,一個是“xyx”,一個是指向“xyx”的引用對象s。

    第十,Math.round(11.5)等於多少? Math.round(-11.5)等於多少?

    Math.round(11.5)返回(long)12,Math.round(-11.5)返回(long)-11;

    第十一,short s1 = 1; s1 = s1 + 1;有什么錯? short s1 = 1; s1 += 1;有什么錯?

    short s1 = 1; s1 = s1 + 1;有錯,s1是short型,s1+1是int型,不能顯式轉化為short型。可修改為s1 =(short)(s1 + 1) 。short s1 = 1; s1 += 1正確。

    第十二,sleep() 和 wait() 有什么區別? 搞線程的最愛
    sleep()方法是使線程停止一段時間的方法。在sleep 時間間隔期滿后,線程不一定立即恢復執行。這是因為在那個時刻,其它線程可能正在運行而且沒有被調度為放棄執行,除非(a)“醒來”的線程具有更高的優先級
    (b)正在運行的線程因為其它原因而阻塞。
    wait()是線程交互時,如果線程對一個同步對象x 發出一個wait()調用,該線程會暫停執行,被調對象進入等待狀態,直到被喚醒或等待時間到。

    第十三,Java有沒有goto?
    Goto java中的保留字,現在沒有在java中使用。

    第十四,數組有沒有length()這個方法? String有沒有length()這個方法?

    數組沒有length()這個方法,有length的屬性。
    String有有length()這個方法。

    第十五,Overload和Override的區別。Overloaded的方法是否可以改變返回值的類型?

    方法的重寫Overriding和重載Overloading是Java多態性的不同表現。重寫Overriding是父類與子類之間多態性的一種表現,重載Overloading是一個類中多態性的一種表現。如果在子類中定義某方法與其父類有相同的名稱和參數,我們說該方法被重寫 (Overriding)。子類的對象使用這個方法時,將調用子類中的定義,對它而言,父類中的定義如同被“屏蔽”了。如果在一個類中定義了多個同名的方法,它們或有不同的參數個數或有不同的參數類型,則稱為方法的重載(Overloading)。Overloaded的方法是可以改變返回值的類型。

    第十六,Set里的元素是不能重復的,那么用什么方法來區分重復與否呢? 是用==還是equals()? 它們有何區別?

    Set里的元素是不能重復的,那么用iterator()方法來區分重復與否。equals()是判讀兩個Set是否相等。
    equals()和==方法決定引用值是否指向同一對象equals()在類中被覆蓋,為的是當兩個分離的對象的內容和類型相配的話,返回真值。

    第十七,給我一個你最常見到的runtime exception。
    ArithmeticException, ArrayStoreException, BufferOverflowException, BufferUnderflowException, CannotRedoException, CannotUndoException, ClassCastException, CMMException, ConcurrentModificationException, DOMException, EmptyStackException, IllegalArgumentException, IllegalMonitorStateException, IllegalPathStateException, IllegalStateException,
    ImagingOpException, IndexOutOfBoundsException, MissingResourceException, NegativeArraySizeException, NoSuchElementException, NullPointerException, ProfileDataException, ProviderException, RasterFORMatException, SecurityException, SystemException, UndeclaredThrowableException, UnmodifiableSetException, UnsupportedOperationException

    第十八,error和exception有什么區別?
    error 表示恢復不是不可能但很困難的情況下的一種嚴重問題。比如說內存溢出。不可能指望程序能處理這樣的情況。
    exception 表示一種設計或實現問題。也就是說,它表示如果程序運行正常,從不會發生的情況。

    第十九,List, Set, Map是否繼承自Collection接口?
    List,Set是

    Map不是

    第二十,abstract class和interface有什么區別?

    聲明方法的存在而不去實現它的類被叫做抽象類(abstract class),它用于要創建一個體現某些基本行為的類,并為該類聲明方法,但不能在該類中實現該類的情況。不能創建abstract 類的實例。然而可以創建一個變量,其類型是一個抽象類,并讓它指向具體子類的一個實例。不能有抽象構造函數或抽象靜態方法。Abstract 類的子類為它們父類中的所有抽象方法提供實現,否則它們也是抽象類為。取而代之,在子類中實現該方法。知道其行為的其它類可以在類中實現這些方法。
    接口(interface)是抽象類的變體。在接口中,所有方法都是抽象的。多繼承性可通過實現這樣的接口而獲得。接口中的所有方法都是抽象的,沒有一個有程序體。接口只可以定義static final成員變量。接口的實現與子類相似,除了該實現類不能從接口定義中繼承行為。當類實現特殊接口時,它定義(即將程序體給予)所有這種接口的方法。然后,它可以在實現了該接口的類的任何對象上調用接口的方法。由于有抽象類,它允許使用接口名作為引用變量的類型。通常的動態聯編將生效。引用可以轉換到接口類型或從接口類型轉換,instanceof 運算符可以用來決定某對象的類是否實現了接口。

    第二十一,abstract的method是否可同時是static,是否可同時是native,是否可同時是synchronized?

    都不能

    第二十二,接口是否可繼承接口? 抽象類是否可實現(implements)接口? 抽象類是否可繼承實體類(concrete class)?
    接口可以繼承接口。抽象類可以實現(implements)接口,抽象類是否可繼承實體類,但前提是實體類必須有明確的構造函數。

    第二十三,啟動一個線程是用run()還是start()?
    啟動一個線程是調用start()方法,使線程所代表的虛擬處理機處于可運行狀態,這意味著它可以由JVM調度并執行。這并不意味著線程就會立即運行。run()方法可以產生必須退出的標志來停止一個線程。

    第二十四,構造器Constructor是否可被override?
    構造器Constructor不能被繼承,因此不能重寫Overriding,但可以被重載Overloading。

    第二十五,是否可以繼承String類?
    String類是final類故不可以繼承。

    第二十六,當一個線程進入一個對象的一個synchronized方法后,其它線程是否可進入此對象的其它方法?
    不能,一個對象的一個synchronized方法只能由一個線程訪問。

    第二十七,try {}里有一個return語句,那么緊跟在這個try后的finally {}里的code會不會被執行,什么時候被執行,在return前還是后?

    會執行,在return前執行。

    第二十八,編程題: 用最有效率的方法算出2乘以8等於幾?

    有C背景的程序員特別喜歡問這種問題。

    2 << 3

    第二十九,兩個對象值相同(x.equals(y) == true),但卻可有不同的hash code,這句話對不對? 
    不對,有相同的hash code。

    第三十,當一個對象被當作參數傳遞到一個方法后,此方法可改變這個對象的屬性,并可返回變化后的結果,那么這里到底是值傳遞還是引用傳遞?

    是值傳遞。Java 編程語言只由值傳遞參數。當一個對象實例作為一個參數被傳遞到方法中時,參數的值就是對該對象的引用。對象的內容可以在被調用的方法中改變,但對象的引用是永遠不會改變的。

    第三十一,swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?

    switch(expr1)中,expr1是一個整數表達式。因此傳遞給 switch 和 case 語句的參數應該是 int、 short、 char 或者 byte。long,string 都不能作用于swtich。

    第三十二,編程題: 寫一個Singleton出來。

    Singleton模式主要作用是保證在Java應用程序中,一個類Class只有一個實例存在。
    一般Singleton模式通常有幾種種形式:
    第一種形式: 定義一個類,它的構造函數為private的,它有一個static的private的該類變量,在類初始化時實例話,通過一個public的getInstance方法獲取對它的引用,繼而調用其中的方法。
    public class Singleton {
      private Singleton(){}
      //在自己內部定義自己一個實例,是不是很奇怪?
      //注意這是private 只供內部調用
      private static Singleton instance = new Singleton();
      //這里提供了一個供外部訪問本class的靜態方法,可以直接訪問  
      public static Singleton getInstance() {
        return instance;   
       }
    }
    第二種形式:
    public class Singleton {
      private static Singleton instance = null;
      public static synchronized Singleton getInstance() {
      //這個方法比上面有所改進,不用每次都進行生成對象,只是第一次     
      //使用時生成實例,提高了效率!
      if (instance==null)
        instance=new Singleton();
    return instance;   }
    }
    其他形式:
    定義一個類,它的構造函數為private的,所有方法為static的。
    一般認為第一種形式要更加安全些

    第三十三 Hashtable和HashMap
    Hashtable繼承自Dictionary類,而HashMap是Java1.2引進的Map interface的一個實現

    HashMap允許將null作為一個entry的key或者value,而Hashtable不允許

    還有就是,HashMap把Hashtable的contains方法去掉了,改成containsvalue和containsKey。因為contains方法容易讓人引起誤解。

    最大的不同是,Hashtable的方法是Synchronize的,而HashMap不是,在
    多個線程訪問Hashtable時,不需要自己為它的方法實現同步,而HashMap
    就必須為之提供外同步。

    posted @ 2005-07-31 19:00 小海船 閱讀(101) | 評論 (0)編輯 收藏

    CSDN  (原作)
      
    關鍵字     java util collection list map set hashmap 集合 鏈表 哈希
      線性表,鏈表,哈希表是常用的數據結構,在進行Java開發時,JDK已經為我們提供了一系列相應的類來實現基本的數據結構。這些類均在java.util包中。本文試圖通過簡單的描述,向讀者闡述各個類的作用以及如何正確使用這些類。

    Collection
    ├List
    │├LinkedList
    │├ArrayList
    │└Vector
    │ └Stack
    └Set
    Map
    ├Hashtable
    ├HashMap
    └WeakHashMap

    Collection接口
      Collection是最基本的集合接口,一個Collection代表一組Object,即Collection的元素(Elements)。一些Collection允許相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接繼承自Collection的類,Java SDK提供的類都是繼承自Collection的“子接口”如List和Set。
      所有實現Collection接口的類都必須提供兩個標準的構造函數:無參數的構造函數用于創建一個空的Collection,有一個Collection參數的構造函數用于創建一個新的Collection,這個新的Collection與傳入的Collection有相同的元素。后一個構造函數允許用戶復制一個Collection。
      如何遍歷Collection中的每一個元素?不論Collection的實際類型如何,它都支持一個iterator()的方法,該方法返回一個迭代子,使用該迭代子即可逐一訪問Collection中每一個元素。典型的用法如下:
        Iterator it = collection.iterator(); // 獲得一個迭代子
        while(it.hasNext()) {
          Object obj = it.next(); // 得到下一個元素
        }
      由Collection接口派生的兩個接口是List和Set。

    List接口
      List是有序的Collection,使用此接口能夠精確的控制每個元素插入的位置。用戶能夠使用索引(元素在List中的位置,類似于數組下標)來訪問List中的元素,這類似于Java的數組。
    和下面要提到的Set不同,List允許有相同的元素。
      除了具有Collection接口必備的iterator()方法外,List還提供一個listIterator()方法,返回一個ListIterator接口,和標準的Iterator接口相比,ListIterator多了一些add()之類的方法,允許添加,刪除,設定元素,還能向前或向后遍歷。
      實現List接口的常用類有LinkedList,ArrayList,Vector和Stack。

    LinkedList類
      LinkedList實現了List接口,允許null元素。此外LinkedList提供額外的get,remove,insert方法在LinkedList的首部或尾部。這些操作使LinkedList可被用作堆棧(stack),隊列(queue)或雙向隊列(deque)。
      注意LinkedList沒有同步方法。如果多個線程同時訪問一個List,則必須自己實現訪問同步。一種解決方法是在創建List時構造一個同步的List:
        List list = Collections.synchronizedList(new LinkedList(...));

    ArrayList類
      ArrayList實現了可變大小的數組。它允許所有元素,包括null。ArrayList沒有同步。
    size,isEmpty,get,set方法運行時間為常數。但是add方法開銷為分攤的常數,添加n個元素需要O(n)的時間。其他的方法運行時間為線性。
      每個ArrayList實例都有一個容量(Capacity),即用于存儲元素的數組的大小。這個容量可隨著不斷添加新元素而自動增加,但是增長算法并沒有定義。當需要插入大量元素時,在插入前可以調用ensureCapacity方法來增加ArrayList的容量以提高插入效率。
      和LinkedList一樣,ArrayList也是非同步的(unsynchronized)。

    Vector類
      Vector非常類似ArrayList,但是Vector是同步的。由Vector創建的Iterator,雖然和ArrayList創建的Iterator是同一接口,但是,因為Vector是同步的,當一個Iterator被創建而且正在被使用,另一個線程改變了Vector的狀態(例如,添加或刪除了一些元素),這時調用Iterator的方法時將拋出ConcurrentModificationException,因此必須捕獲該異常。

    Stack 類
      Stack繼承自Vector,實現一個后進先出的堆棧。Stack提供5個額外的方法使得Vector得以被當作堆棧使用。基本的push和pop方法,還有peek方法得到棧頂的元素,empty方法測試堆棧是否為空,search方法檢測一個元素在堆棧中的位置。Stack剛創建后是空棧。

    Set接口
      Set是一種不包含重復的元素的Collection,即任意的兩個元素e1和e2都有e1.equals(e2)=false,Set最多有一個null元素。
      很明顯,Set的構造函數有一個約束條件,傳入的Collection參數不能包含重復的元素。
      請注意:必須小心操作可變對象(Mutable Object)。如果一個Set中的可變元素改變了自身狀態導致Object.equals(Object)=true將導致一些問題。

    Map接口
      請注意,Map沒有繼承Collection接口,Map提供key到value的映射。一個Map中不能包含相同的key,每個key只能映射一個value。Map接口提供3種集合的視圖,Map的內容可以被當作一組key集合,一組value集合,或者一組key-value映射。

    Hashtable類  Hashtable繼承Map接口,實現一個key-value映射的哈希表。任何非空(non-null)的對象都可作為key或者value。
      添加數據使用put(key, value),取出數據使用get(key),這兩個基本操作的時間開銷為常數。
    Hashtable通過initial capacity和load factor兩個參數調整性能。通常缺省的load factor 0.75較好地實現了時間和空間的均衡。增大load factor可以節省空間但相應的查找時間將增大,這會影響像get和put這樣的操作。
    使用Hashtable的簡單示例如下,將1,2,3放到Hashtable中,他們的key分別是”one”,”two”,”three”:
        Hashtable numbers = new Hashtable();
        numbers.put(“one”, new Integer(1));
        numbers.put(“two”, new Integer(2));
        numbers.put(“three”, new Integer(3));
      要取出一個數,比如2,用相應的key:
        Integer n = (Integer)numbers.get(“two”);
        System.out.println(“two = ” + n);
      由于作為key的對象將通過計算其散列函數來確定與之對應的value的位置,因此任何作為key的對象都必須實現hashCode和equals方法。hashCode和equals方法繼承自根類Object,如果你用自定義的類當作key的話,要相當小心,按照散列函數的定義,如果兩個對象相同,即obj1.equals(obj2)=true,則它們的hashCode必須相同,但如果兩個對象不同,則它們的hashCode不一定不同,如果兩個不同對象的hashCode相同,這種現象稱為沖突,沖突會導致操作哈希表的時間開銷增大,所以盡量定義好的hashCode()方法,能加快哈希表的操作。
      如果相同的對象有不同的hashCode,對哈希表的操作會出現意想不到的結果(期待的get方法返回null),要避免這種問題,只需要牢記一條:要同時復寫equals方法和hashCode方法,而不要只寫其中一個。
      Hashtable是同步的。

    HashMap類
      HashMap和Hashtable類似,不同之處在于HashMap是非同步的,并且允許null,即null value和null key。,但是將HashMap視為Collection時(values()方法可返回Collection),其迭代子操作時間開銷和HashMap的容量成比例。因此,如果迭代操作的性能相當重要的話,不要將HashMap的初始化容量設得過高,或者load factor過低。

    WeakHashMap類
      WeakHashMap是一種改進的HashMap,它對key實行“弱引用”,如果一個key不再被外部所引用,那么該key可以被GC回收。

    總結
      如果涉及到堆棧,隊列等操作,應該考慮用List,對于需要快速插入,刪除元素,應該使用LinkedList,如果需要快速隨機訪問元素,應該使用ArrayList。
      如果程序在單線程環境中,或者訪問僅僅在一個線程中進行,考慮非同步的類,其效率較高,如果多個線程可能同時操作一個類,應該使用同步的類。
      要特別注意對哈希表的操作,作為key的對象要正確復寫equals和hashCode方法。
      盡量返回接口而非實際的類型,如返回List而非ArrayList,這樣如果以后需要將ArrayList換成LinkedList時,客戶端代碼不用改變。這就是針對抽象編程。
    posted @ 2005-07-31 18:22 小海船 閱讀(109) | 評論 (0)編輯 收藏

    package iss.com.equals;

    import java.util.Date;

    class CountIsable {

     private Date date;

     private String accountNo;

     private String bankCode;

     public CountIsable(Date transactionTime, String accountNo, String bankCode) {
      this.date = transactionTime;
      this.accountNo = accountNo;
      this.bankCode = bankCode;
     }

     public CountIsable(String accountNo, String bankCode) {
      this.accountNo = accountNo;
      this.bankCode = bankCode;
     }
                   
     public boolean equals(CountIsable mapKey) {
      if (DateUtil.compareDate(date, mapKey.getDate()) == 0
        && accountNo.equals(mapKey.getAccountNo())) {
       if (mapKey.getBankCode() == null
         || mapKey.getBankCode().equals(bankCode))
        return true;
      }
      return false;
     }
     public boolean equals(Object key) {
      CountIsable mapKey=(CountIsable)key;
      if (DateUtil.compareDate(date, mapKey.getDate()) == 0
        && accountNo.equals(mapKey.getAccountNo())) {
       if (mapKey.getBankCode() == null
         || mapKey.getBankCode().equals(bankCode))
        return true;
      }
      return false;
     }

     public String toString() {
      return date.toString() + accountNo + bankCode;
     }

    public int hashCode() {
     int temp =(date.toString() + accountNo + bankCode).hashCode(); 
      return temp;
     }

     public String getAccountNo() {
      return accountNo;
     }

     public String getBankCode() {
      return bankCode;
     }

     public Date getDate() {
      return date;
     }
    }

    posted @ 2005-07-29 10:04 小海船 閱讀(529) | 評論 (0)編輯 收藏

    僅列出標題
    共3頁: 上一頁 1 2 3 
    主站蜘蛛池模板: 久草视频在线免费| 亚洲国产中文在线视频| 成年女人午夜毛片免费视频| 久久99毛片免费观看不卡| 色一情一乱一伦一视频免费看| 亚洲一区二区三区高清视频| 亚洲国产精品久久| 亚洲熟女少妇一区二区| 亚洲成年人啊啊aa在线观看| 日本免费观看网站| 亚洲福利视频导航| 亚洲日韩在线观看| 免费不卡中文字幕在线| 毛片免费全部播放一级| 成年网站免费视频A在线双飞| 亚洲精品免费视频| 中文字幕无码日韩专区免费| 中文字幕视频免费在线观看| 四虎一区二区成人免费影院网址| 99亚洲男女激情在线观看| 亚洲人成色77777在线观看 | 人人玩人人添人人澡免费| caoporm碰最新免费公开视频| 美女视频黄频a免费| 特黄特色大片免费| 日韩在线视频线视频免费网站| 精品久久久久亚洲| 美女视频黄频a免费大全视频| 国产成人亚洲综合a∨| 青青免费在线视频| 免费一级毛suv好看的国产网站 | 午夜dj免费在线观看| 处破痛哭A√18成年片免费| 四虎免费在线观看| 国产精品免费电影| 亚洲av无码不卡私人影院| 亚洲日韩精品无码专区网站| 区久久AAA片69亚洲| 亚洲国产精品乱码一区二区| 久久夜色精品国产噜噜亚洲AV| 亚洲精品视频在线免费|