Guava(一)Lists與Maps

轉載出處:http://ajoo.iteye.com/blog/735368


 


花開花落,花落花開。少年子弟江湖老,紅顏少女的兒子都會打醬油反三俗了. 

驀然回首, 那個彷彿剛剛還在上幼兒園, 拉着我的手讓我帶着到麥當勞買雞塊冰激凌吃的小屁孩兒; 上了小學, 抱着我給買的盜版commando苦苦鑽研攻略的小表弟, 開始寫java程序了! 

暑假去小表弟學校宿舍晃了一下. 書桌上隨手堆着的可樂礦泉水瓶; 書桌下凌亂的鞋子, 鼠標; 寢室門上的個性標語; 隔壁在炎夏裏半裸着看片子(木有看清是女主是否半裸)的猥瑣男生, 都讓俺情不自禁地小資起來: 唉, 世界是你們的了! 

唯一地遺憾是沒有重溫一下女生寢室的風光 --- 上了年紀了, jailbreak門口大媽的身手不再了呀! 

小兄弟是個努力的好童鞋. 於是咱自然當仁不讓開始介紹UML, SOA, 4GL, J2EE, Agile Programming, JSR168X --- 噢, 不好意思, 又不小心yy了, 俺是粗淫, 這些說實話不懂地. 

咳嗽, 是介紹JUnit, TDD, 和瓜娃 --- 就是Google Collection的重裝上陣: Guava


一. ListsMaps 

介紹瓜娃主要是覺得它是個老老實實的能幫助寫代碼的工具庫. 不用把它當作正兒八經的什麼東西學習 (說實話, 那裏面的東西俺估計也就接觸過兩成了不起了), 把那個jar文件放到你的classpath裏, 然後哪怕你就知道一個庫函數呢, 對景的時候也是個幫手啊. 

比如, 最簡單地, 用java5以上的話(2010年了, 還在用上古神器jdk1.3或者1.4的首長請舉手. 敬禮! 首長辛苦了!), 你怎麼new一個ArrayList呢? 這樣吧? 

Java代碼  收藏代碼
  1. List<String> list = new ArrayList<String>();  


怎麼new一個HashMap呢? 是不是這樣? 
Java代碼  收藏代碼
  1. Map<String, Integer> map = new HashMap<String, Integer>();  


對俺們這些用慣了瓜娃的懶人, 寫那個<>裏面的東東兩次就覺得累得慌, 除非一些特殊的場合不想依賴瓜娃的jar文件的, 俺們一般都改寫成: 

Java代碼  收藏代碼
  1. List<String> list = Lists.newArrayList();  

Java代碼  收藏代碼
  1. Map<String, Integer> list = Maps.newHashMap();  


Lists和Maps是兩個工具類, Lists.newArrayList()其實和new ArrayList()幾乎一模一樣, 唯一它幫你做的(其實是javac幫你做的), 就是自動推導(不是"倒")尖括號裏的那坨叉叉. 

這兩個東西要說技術含量, 附加價值差不多趨近於0. 但是越是這種簡單的不用腦子的東西, 越是讓人驚訝地有邪異的吸引力. 我就看過好幾個人說, 他們使用瓜娃的主要目的, 就是newArrayList()和newHashMap(). 畢竟, 這東西每個人每時每刻差不多都要用到吧? 

當然, 瓜娃提供的遠不止這兩毛五, 買一根小豆冰棍兒都不夠. 比如, 除了new一個空的ArrayList, 你還想往裏放點數據. 直接用jdk的話, 大概是這樣: 

Java代碼  收藏代碼
  1. List<Integer> list = new ArrayList<Integer>();  
  2. list.add(1);  
  3. list.add(2);  
  4. list.add(3);  


用Lists是這樣: 
Java代碼  收藏代碼
  1. List<Integer> list = Lists.newArrayList(123);  


嗯, 是不是有點意思了? 值一個"可愛多"了吧? 


二. ImmutableListImmutableMap 

現在主流java社區傾向於同意, immutable對象(就是說狀態不變)是個好東西. 它能讓程序邏輯變得簡單易懂, 而且減少出錯的可能性. 

JDK目前不提供immutable集合. 瓜娃提供的最主要的immutable集合, 是ImmutableList, ImmutableSet和ImmutableMap. 
顧名思義, 一旦你創建了一個ImmutableList或者ImmutableMap, 你就再也不能改變它了. 它就像你記憶中初戀的那個她, 不管時光荏苒, 滄海桑田, 永遠年輕美麗語笑嫣然 --- 當然, 前提是你還活着. 

那麼怎麼創建ImmutableList呢? 嗯, 除非語言直接提供支持, 這應該是最簡單的方式了: 
Java代碼  收藏代碼
  1. ImmutableList<Integer> list = ImmutableList.of(123);  

ImmutableMap一樣簡單: 
Java代碼  收藏代碼
  1. ImmutableMap<String, Integer> map = ImmutableMap.of(  
  2.     "1"1,  
  3.     "2"2,  
  4.     "3"3  
  5. );  


對比一下用HashMap的情況: 

Java代碼  收藏代碼
  1. Map<String, Integer> map = new HashMap<String, Integer>();  
  2. map.put("1"1);  
  3. map.put("2"2);  
  4. map.put("3"3);  



還是前者舒服吧? 

那麼, 假設你所有的不是事先知道的一些常量. 比如說, 你要從一個數據庫裏讀出一些基本信息保存在內存裏. 用of()就不好使了, 這時候, 可以用builder模式: 
Java代碼  收藏代碼
  1. ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();  
  2. for (...) {  
  3.   builder.put(name, age);  
  4. }  
  5. ImmutableMap<String, Integer> map = builder.build();  


ImmutableList和ImmutableMap最常用的就是創建一些集合常量 (這些常量都是static final的). 

另外一個主要的用途, 是作爲其它Immutable對象內部使用的數據結構. 


三. 討論 

一個也許會存在爭議, 但是瓜娃開發組強烈推薦的使用方法, 是凡是可能的情況下, 給你的函數的返回類型用ImmutableList和ImmutableMap, 而不是它們實現的接口: List和Map. 比如: 

Java代碼  收藏代碼
  1. ImmutableList<String> getNames();  
  2. ImmutableMap<String, Integer> getAgeMap();  

而不是: 
Java代碼  收藏代碼
  1. List<String> getNames();  
  2. Map<String, Integer> getAgeMap();  


爲什麼這樣呢? 這是因爲immutable集合是一類特殊集合, 它們不象ArrayList, HashMap那樣是純粹的實現細節, 相反, 這些類型攜帶了重要的語義信息: 它們是不可變的. 

如果調用者使用了list.add()或者map.put(), 得到的將是UnsupportedOperationException異常. 

通過返回ImmutableMap和ImmutableList, 函數簽名清楚地告訴調用者什麼可以做, 什麼不可以做. 這對大型程序中團隊協作, 代碼理解和維護好處多多. 

實際上, 最有爭議的, 是在jdk的集合框架設計上. Sun把List和Map的接口設計爲mutable(可變的), 但是同時允許實現類不實現某些函數, 比如add(), put(). 一些貌似愛思考地程序員(包括俺)就想啦: 爲啥你不乾脆把寫操作分離出來呢? 這樣當一個人拿到ImmutableList的時候, 他根本就沒有add()可以調用, 更甭說運行時拋異常了? 

Sun對此專門有個回答. 是否信服就由你了. 不過不管喜不喜歡, 我們今天所有的就是這個設計: 一個List可能是可變的也可能是不可變的. 大概還是不要鑽牛角尖, 入鄉隨俗吧. 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章