JAVA

          人生若只如初見,何事秋風(fēng)悲畫扇。

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            50 隨筆 :: 25 文章 :: 157 評(píng)論 :: 0 Trackbacks
                在Java中有許多的容器集合。初一看起來有些糊涂,特別是對(duì)剛接觸Java來說(至少我當(dāng)初就是這樣的)!其實(shí)稍微細(xì)心,深入一點(diǎn)點(diǎn)就會(huì)發(fā)現(xiàn)原來一切都是有規(guī)律的。我想別的事情也會(huì)是如此。
                 Java中的容器,接口都是由一些接口,抽象類及它們的實(shí)現(xiàn)類所組成。而它們?nèi)糠庋b在java.util
          包中。


          1:Collection接口。

                 大多數(shù)的集合都實(shí)現(xiàn)了此接口,它基本方法是add(沒有g(shù)et()方法,實(shí)現(xiàn)類中可能有如Arrylist),添加一對(duì)象。添加成功則返回true ,否則返回false。這是與Map不同的地方。還有一些常用的方法如iterator(),size(),toArray()(注:toArray()是返回一對(duì)象----object數(shù)組,而Arrays----也是java.util下的一個(gè)類,有一個(gè)asList方法它們通常認(rèn)為是各集合之間轉(zhuǎn)換的橋梁)等等!具體用法可以參考API文檔。


          2:Map(映射)
                 Map接口跟Collection接口實(shí)際上沒有半點(diǎn)關(guān)系。集合中的每一個(gè)元素都包含一對(duì)鍵對(duì)對(duì)象和值對(duì)象,集合中沒有重復(fù)的鍵對(duì)象,值對(duì)象可以重復(fù)。它的有些實(shí)現(xiàn)類能對(duì)集合中的鍵對(duì)象進(jìn)行排序。與Collection截然不同的是,它其中所存取的是一些值與名相對(duì)應(yīng)的數(shù)據(jù)。也就是一個(gè)Key對(duì)應(yīng)一個(gè)Value的方式來存儲(chǔ)。所以它就有與之對(duì)應(yīng)的一些方法如:put (K key, V value)等等,更多可以參考API文檔。

          3:List(列表)
                集合中的對(duì)象按索引位置排序,可以有重復(fù)對(duì)象,允許按照對(duì)象在集合中的索引位置檢索對(duì)象

          4:Set(集)
                集合中的對(duì)象中按特定的方式排序,并且沒有重復(fù)對(duì)象。它的有些實(shí)現(xiàn)類能對(duì)集合中的對(duì)象
          按特定的方式排序

          5:迭代器:Iterator
                 它是一個(gè)接口,只有三個(gè)方法hasnext(),next(),remove()只有最后一個(gè)是可選的,也就是remove()是可選(在實(shí)現(xiàn)的時(shí)候)。其可選性也意味著它的實(shí)現(xiàn)類中,remove方法是可有可無的。例如,若有一個(gè)如下的List 實(shí)例。
                  
              Arrylist al = new Arrylist();
              Object[] ob 
          = al.toArray();
              List list 
          = Arrays.asList(ob);
              Iterator itor 
          = list.iterator();
              itor.remove();      
          //Error 

                  當(dāng)調(diào)用Ierator itr = list.iterator()方法返回一迭代器的時(shí)候,便不支持remove方法,所以當(dāng)你再使用irt.remove()時(shí)程序就是異常!

                  使用此迭代器要注意的是remove()方法。它所刪除的是指指針(暫這么叫著)上次所移經(jīng)過的位置(Removes from the underlying collection the last element returned by the iterator (optional operation).)。我個(gè)人覺得有點(diǎn)象在JDBC中的ResultSet rs = ....;rs.last();rowsCount=rs.getRow();類似呢。
                  前面所講的,由于clollection提供了iterator()方法,所以迭代器是很容易實(shí)現(xiàn)的!

          6:常用實(shí)現(xiàn)類的一些繼承關(guān)系:

                  Collections,它是Java.util下的一個(gè)類。它為我們提供了許多有用的方法,如sort(...),max()等其具體用法可以參考API文檔,比如sort(List list);中l(wèi)ist內(nèi)的所有元素都必須實(shí)現(xiàn)Comparable接口(All elements in the list must implement the Comparable interface)。

                
          Arrylist ,它是List接口的實(shí)現(xiàn)類,而List則是繼承于Collection。
                 LinkedList,它也是間接對(duì)Colections的實(shí)現(xiàn)。用linkedlist的一些方法如addfirst(),removefirst(),addlast()等等可以用來實(shí)現(xiàn)如C中的堆棧,鏈表。(對(duì)于頻繁使用插入與刪除操作使用linkedlist是個(gè)不錯(cuò)的選擇,對(duì)于經(jīng)常進(jìn)行索引操作則arrylist較好)。


                  HashSet(散列表),它實(shí)現(xiàn)了Set接口,也就意味著它的元素不能有重復(fù)值出現(xiàn)。并且在HashSet中沒有g(shù)et()方法,但可以通過iterator()來實(shí)現(xiàn)。要注意的是假如要在HasSet中存放一些對(duì)象,那么你得重定義hashCode()與equals()二個(gè)方法來保不可以存放相同的內(nèi)容的元素。對(duì)于hashcode()所返回的值,hashset用它來計(jì)算(通過特定的函數(shù))該對(duì)象在內(nèi)存中的存放位置;后者主要用來判斷二個(gè)對(duì)象的內(nèi)容是否相等而返回對(duì)應(yīng)的boolen型。
                 TreeSet,主要用來對(duì)元素進(jìn)行排序操作,假如要往其中添加對(duì)象,則對(duì)象得實(shí)現(xiàn)
          Comparable接口。(假如不要對(duì)元素排序,則一般可選用HashSet)。

                 HashMap,主要特點(diǎn)是存放的一個(gè)鍵值對(duì),一些有用的方法是可返回視圖(我覺得可以把它理解為一個(gè)集合)如:keyset(),values(),entyset()等。
                 關(guān)于對(duì)HashMap的小步深入理解:
                 HashMap是由鍵值對(duì)組成的,關(guān)于HashMap有二點(diǎn)要注意:1. 它的鍵只能是一個(gè)Object對(duì)象。 2. 當(dāng)二個(gè)HashMap用equals方法比較時(shí),實(shí)際的比較是它的Key,而與Value無關(guān)。

                 HashMap的主要特點(diǎn)是其底層的物理存放與查找用到了hash函數(shù)相關(guān)的原理。根據(jù)java窗口的查找原理,查找最快的應(yīng)該是由數(shù)組經(jīng)過工具類Arrays的Arrays.sort方法排序后,再用此工具類的Arrays.binarySearch方法進(jìn)行查找。對(duì)于HashMap的數(shù)據(jù)查找就是用這個(gè)原理實(shí)現(xiàn)的,另外由于數(shù)組的致命缺點(diǎn)就是它是定長(zhǎng)的,而HashMap卻是可以動(dòng)態(tài)增加,所以查找過程其實(shí)不是將Key本身放在一個(gè)Object[]的數(shù)組中,而是將與Key有密切相關(guān)的信息做為索引Object[]數(shù)組的下標(biāo),然后根據(jù)此下標(biāo)去Object[]數(shù)組中查找數(shù)據(jù),這個(gè)所謂密切相關(guān)的信息就是通過Key.hashCode()函數(shù)所產(chǎn)生的數(shù)字??上攵?dāng)HashMap中的Key很多時(shí),各Key所產(chǎn)生的hashCode肯定會(huì)有重合的現(xiàn)象發(fā)生,為了防止此情況發(fā)生,所以根據(jù)這個(gè)索引在數(shù)組中得到的對(duì)象并不是最終要查找的數(shù)據(jù),查到的其實(shí)是一個(gè)list列表,在這列表中列出了由于HashMap中的Key通過散列后具有相同hashCode的全部對(duì)像。可以想像得到,這個(gè)列表中的對(duì)像應(yīng)該是相當(dāng)少的。對(duì)于對(duì)Object[]數(shù)據(jù)下下標(biāo)定位后,就得到了這個(gè)列表,接下來equals函數(shù)粉墨登場(chǎng)了,若能返回true則表示此對(duì)象已經(jīng)存在,這時(shí)HashMap會(huì)用新的值覆蓋舊值,若不存在則會(huì)做添加操作了。

                 在HashMap的初始化中,會(huì)涉及到二個(gè)比較重要的值,也是影響其性能的二個(gè)重要值:Object[]的長(zhǎng)度(v1)、Object[]中實(shí)際已經(jīng)存放了多少object對(duì)象(v2)。在我們初始化HashMap時(shí)會(huì)有:HashMap(int initialCapacity, float loadFactor) 這個(gè)方法,initialCapacity表示object[]的初始化長(zhǎng)度,loadFactor表示允許此在Object[]存放數(shù)據(jù)的百分比(loadFactor=v2/v1),系統(tǒng)默認(rèn)的是0.75(也就是可以存放占o(jì)bject[]數(shù)組3/4的數(shù)據(jù))。當(dāng)HashMap里的數(shù)據(jù)不斷增加時(shí),它會(huì)自動(dòng)地按數(shù)量級(jí)擴(kuò)展Object[]的長(zhǎng)度(應(yīng)該盡量阻止Object[]的自動(dòng)增加,這樣不但消費(fèi)資源對(duì)于以后的查找、插入操作也不利)。
          HashMap結(jié)論:對(duì)于Key一定要實(shí)現(xiàn)hashCode() and equals方法,且盡量要讓hashCode散布得均勻。這樣才能充分利用Object[]數(shù)組,不然,會(huì)導(dǎo)致Object[]得不到充分利用,而在Object[index]具體對(duì)應(yīng)的對(duì)象list列表中存放很多Key對(duì)像,而在list中進(jìn)行查找操作是比較耗時(shí)的。

                 根據(jù)以上原理,HashMap的簡(jiǎn)單實(shí)現(xiàn):
          import java.util.*;
          import com.bruceeckel.util.*;

          public class SimpleHashMap extends AbstractMap {
            // Choose a prime number for the hash table
            // size, to achieve a uniform distribution:
            private static final int SZ = 997;
            private LinkedList[] bucket = new LinkedList[SZ];
            public Object put(Object key, Object value) {
              Object result = null;
              int index = key.hashCode() % SZ;
              if(index < 0) index = -index;
              if(bucket[index] == null)
                bucket[index] = new LinkedList();
              LinkedList pairs = bucket[index];
              MPair pair = new MPair(key, value);
              ListIterator it = pairs.listIterator();
              boolean found = false;
              while(it.hasNext()) {
                Object iPair = it.next();
                if(iPair.equals(pair)) {
                  result = ((MPair)iPair).getValue();
                  it.set(pair); // Replace old with new
                  found = true;
                  break;
                }
              }
              if(!found)
                bucket[index].add(pair);
              return result;
            }
            public Object get(Object key) {
              int index = key.hashCode() % SZ;
              if(index < 0) index = -index;
              if(bucket[index] == null) return null;
              LinkedList pairs = bucket[index];
              MPair match = new MPair(key, null);
              ListIterator it = pairs.listIterator();
              while(it.hasNext()) {
                Object iPair = it.next();
                if(iPair.equals(match))
                  return ((MPair)iPair).getValue();
              }
              return null;
            }
            public Set entrySet() {
              Set entries = new HashSet();
              for(int i = 0; i < bucket.length; i++) {
                if(bucket[i] == null) continue;
                Iterator it = bucket[i].iterator();
                while(it.hasNext())
                  entries.add(it.next());
              }
              return entries;
            }
            public static void main(String[] args) {
              SimpleHashMap m = new SimpleHashMap();
              Collections2.fill(m, Collections2.geography, 25);
              System.out.println(m);
            }
          } ///:~



                  TreeMap,它與HashMap差不多,不過是增加了對(duì)元素的排序功能,所以運(yùn)行速度也就當(dāng)然沒有hashmap來得快了。
                   以下是HashMap的一個(gè)實(shí)例(在對(duì)DB進(jìn)行操作的時(shí)候很有用):
          HashMap valueMap;
          //this function just get key-value form DB ,defined by yourself
          valueMap = commondb.getElementStringValues("COMMENT_ID""content");
          java.util.Set tempkeys 
          = valueMap.entrySet();
                      java.util.Iterator keys 
          = tempkeys.iterator();
          while(keys.hasNext())
                          
          {
                              java.util.Map.Entry me
          =(java.util.Map.Entry)keys.next();
          String value 
          = me.getValue();
          int key = me.getKey();
          }


                 要注意的是entrySet()所返回的每一個(gè)元素都是Map.Entry類型的!(Returns a collection view of the mappings contained in this map. Each element in the returned collection is a Map.Entry.)      
           
                 Properties,繼承于hashtable。這個(gè)東東相信我們比較的喜歡了(在i18n,ant中可以是常見得很),呵呵。它可以從外部導(dǎo)入屬性文件。文件中的鍵值都是String類型。just like this:
                  
          company=study
          author
          =Jkallen
          copyright
          =2005-2006
                 
                   操作如下:
                 
          import java.util.*;
          import java.io.*;
          class PropTest
          {
              
          public static void main(String[] args)
              
          {
                  
          /*Properties pps=System.getProperties();
                  pps.list(System.out);
          */

                  Properties pps
          =new Properties();
                  
          try
                  
          {
                      pps.load(
          new FileInputStream("winsun.ini"));
                      Enumeration 
          enum=pps.propertyNames();
                      
          while(enum.hasMoreElements())
                      
          {
                          String strKey
          =(String)enum.nextElement();
                          String strValue
          =pps.getProperty(strKey);
                          
                          System.out.println(strKey
          +"="+strValue);
                      }

                  }

                  
          catch(Exception e)
                  
          {
                      e.printStackTrace();
                  }

              }

          }

                  其用法可以查看API文檔呢。

                  Java中的集合容器確實(shí)不少呢...其中有些我們也許一直都用不到,(我也是查看了些相關(guān)的資料再加上自己的一些想法整理了一下,希望對(duì)相關(guān)朋友有用!)可是重要的是知道我們?cè)趯?shí)現(xiàn)一個(gè)功能時(shí)應(yīng)該選用哪種集合類來實(shí)現(xiàn)就OK了。

                 參考資料:JDK1.5文檔,Think in Java,孫鑫/張孝祥JAVA資料
          posted on 2006-01-12 00:21 Jkallen 閱讀(16895) 評(píng)論(9)  編輯  收藏 所屬分類: JEE學(xué)習(xí)

          評(píng)論

          # re: Java容器集合學(xué)習(xí)心得 2006-03-24 14:19 路過
          幸好有你! ::)  回復(fù)  更多評(píng)論
            

          # re: Java容器集合學(xué)習(xí)心得 2008-06-24 08:54 趙天宇
          寫得不錯(cuò)。希望繼續(xù)發(fā)表一些這樣的文章!  回復(fù)  更多評(píng)論
            

          # re: Java容器集合學(xué)習(xí)心得 2008-06-30 11:15
          很好的東西,有時(shí)間我也多寫寫!!!  回復(fù)  更多評(píng)論
            

          # re: Java容器集合學(xué)習(xí)心得 2008-08-08 16:23 路過
          寫得相當(dāng)好  回復(fù)  更多評(píng)論
            

          # re: Java容器集合學(xué)習(xí)心得 2009-03-03 19:47 快樂一休
          寫的很好呀~~~~  回復(fù)  更多評(píng)論
            

          # re: Java容器集合學(xué)習(xí)心得 2009-11-26 09:57 愛美女
          很有用 ,不錯(cuò) ~  回復(fù)  更多評(píng)論
            

          # re: Java容器集合學(xué)習(xí)心得 2010-12-10 17:04 java追求者
          值得珍藏和學(xué)習(xí)  回復(fù)  更多評(píng)論
            

          # re: Java容器集合學(xué)習(xí)心得 2012-06-18 09:35 丫的
          可以。??墒强拥臎]學(xué)完!  回復(fù)  更多評(píng)論
            

          # re: Java容器集合學(xué)習(xí)心得 2014-01-23 16:10 cook5210
          謝謝樓主 謝的很詳細(xì)  回復(fù)  更多評(píng)論
            

          主站蜘蛛池模板: 平南县| 巢湖市| 古田县| 鹤岗市| 陈巴尔虎旗| 九江县| 莫力| 淮阳县| 溆浦县| 鹤岗市| 武宁县| 乐陵市| 江西省| 凌海市| 鄂伦春自治旗| 万载县| 江都市| 昌图县| 克拉玛依市| 抚松县| 香港 | 荔浦县| 通榆县| 广河县| 北流市| 临沂市| 阳泉市| 揭西县| 开鲁县| 内江市| 南陵县| 山阳县| 富阳市| 河池市| 秦皇岛市| 卢湾区| 尉氏县| 阳江市| 福海县| 大埔区| 榆社县|