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

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

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

    John Jiang

    a cup of Java, cheers!
    https://github.com/johnshajiang/blog

       :: 首頁 ::  :: 聯系 :: 聚合  :: 管理 ::
      131 隨筆 :: 1 文章 :: 530 評論 :: 0 Trackbacks
    你所不知道的五件事情--Java集合框架API(第一部分)
                                                      --定制與擴展Java集合框架
    這是Ted NewardIBM developerWorks5 things系列文章中的一篇,講述了關于Java集合框架的一些應用竅門,值得大家學習。(2010.05.28最后更新)

        概要:Java集合API遠不止是數組的替代品,盡管那是一個不壞的認知起點。Ted Neward展示了5個能更大利用集合框架的竅門,包含一個定制并擴展Java集合API的入門級應用。

        對于許多Java開發者而言,Java集合API是標準的Java數組及其全部缺點的必要替代品。將集合框架主要與ArrayList聯系起來并不是一個錯誤,但集合框架中還有許多需要關注的地方。
        同樣地,盡管對于名-值或鍵-值對來說,Map(及其它的常選實現HashMap)是極好的,但仍沒理由把自己限制在這些熟悉的工具中。你可使用正確的 API,甚至是正確的集合API去修正許多存在潛在錯誤的代碼。
        本文是5 things系列的第二篇文章,也是針對集合框架若干篇文章中的第一篇,因為在我們進行Java編程時,集合框架處于核心地位。開始時,將會看到處理常見工作,例如將Array轉換成List,的便捷(但并不是最通用的)方法。之后,我們將深入研究集合框架中不太常見的主題,例如擴展Java集合框架API并定制一個集合類.

    1. 使用集合對象處理數組
        新接觸Java技術的開發者可能不知道數組是天然包含在Java語言中的,這是為了應對上世紀九十年代早期來自于C++開發者們有關性能的批評。是的,從那以后,我們已經歷了很長時間,當與Java集合類庫相比較時,數組的性能優勢正在變小。
        例如,將數組中的內容導出成一個字符串時,需要遍歷數組,然后將其中的內容連接成一個String類型;然而,集合框架的實現都有其各自不同的 toString實現。
    除了極少數情況,一種好的實踐方式就是盡快將任何數組轉換成集合對象。這就提出了一個問題,有什么最簡單的方法來做這種轉換呢?事實證明,Java集合框架API使這一過程變得簡單,如清單1所示:

    清單1. ArrayToList
    import java.util.*;

    public class ArrayToList
    {
        
    public static void main(String[] args)
        {
            
    // This gives us nothing good
            System.out.println(args);
            
            
    // Convert args to a List of String
            List<String> argList = Arrays.asList(args);
            
            
    // Print them out
            System.out.println(argList);
        }
    }

    注意,返回的List是不可修改的,所以當試圖向其中添加新的元素時,將會拋出UnsupportedOperationException。
        因為Arrays.asList方法對添加到List中的元素使用vararg(可變長參數),你就可使用它輕松地創建被新建對象的List對象。

    2. 迭代的效率不高
        將一個集合對象(特別是該集合是由一數組轉化而成的)中的內容移入到另一個集合對象,或是從一個較大對象集合中刪除一個較小的對象集合,這些都是不常見的需求。
        你可能會嘗試著迭代該集合,然后向其中添加或刪除每一個被找到的元素,但不能這樣做。
        在這個例子中,迭代有很大的缺點:
    • 在每一次添加或刪除動作之后,無法高效地重新調整集合的大小。
    • 為了進行這些操作,在獲取和釋放鎖時會有潛在的并發性夢魘。
    • 當正在進行添加或刪除元素時,其它線程也在操作你的集合,這就會導致競爭條件。
    針對你想添加或刪除元素的集合對象,使用addAll或removeAll方法,你就能避免上述所有問題。

    3. 利用for循環遍歷Iterable對象

        在Java 5中加入的最好的Java語言便捷特性之一,改進的for循環,消除了操作Java集合對象的最后一道障礙。
        在此之前,開發者們必須得手工地獲取Iterator,使用next()方法去獲得Iterator中被指定的對象,以及通過hasNext()方法來檢查是否還有更多的對象。在Java 5之后,我們可以方便地使用for-loop變體來默默地處理上述所有操作。
        準確地說,這種改進并不僅僅針對集合對象,而可用于任何實現了Iterable接口的對象。
        清單2展示了如何將Person對象中的children作為一個Iterator去制成一個列表。不同于操作一個指向內部List的引用(這會允許 Person的外部調用者向你的家庭中添加新的子女--大多數父母會對此感到不快的),Person類型實現了Iterable接口。該方法也能使改進的 for循環可遍歷其中的孩子列表。

    清單2. 改進的for循環:列出你的子女
    // Person.java
    import java.util.*;

    public class Person
        
    implements Iterable<Person>
    {
        
    public Person(String fn, String ln, int a, Person kids)
        {
            
    this.firstName = fn; this.lastName = ln; this.age = a;
            
    for (Person child : kids)
                children.add(child);
        }
        
    public String getFirstName() { return this.firstName; }
        
    public String getLastName() { return this.lastName; }
        
    public int getAge() { return this.age; }
        
        
    public Iterator<Person> iterator() { return children.iterator(); }
        
        
    public void setFirstName(String value) { this.firstName = value; }
        
    public void setLastName(String value) { this.lastName = value; }
        
    public void setAge(int value) { this.age = value; }
        
        
    public String toString() {
            
    return "[Person: " +
                
    "firstName=" + firstName + " " +
                
    "lastName=" + lastName + " " +
                
    "age=" + age + "]";
        }
        
        
    private String firstName;
        
    private String lastName;
        
    private int age;
        
    private List<Person> children = new ArrayList<Person>();
    }

    // App.java
    public class App
    {
        
    public static void main(String[] args)
        {
            Person ted 
    = new Person("Ted""Neward"39,
                
    new Person("Michael""Neward"16),
                
    new Person("Matthew""Neward"10));

            
    // Iterate over the kids
            for (Person kid : ted)
            {
                System.out.println(kid.getFirstName());
            }
        }
    }

    對于域模型,使用Iterable接口會有一些明顯的缺點,因為只有一個對象集合能夠通過iterator()方法得到如此"隱式"的支持。在這種情況下,children集合在何處是確定且透明的,然而,Iterable接口可使程序設計在應對域類型時要容易得多,也會更明顯。

    4. 典型算法與定制算法
        你曾經會想過遍歷一個集合對象,但是從相反的方向呢?這就是典型的Java集合框架算法用得上的地方。
        上述清單2中Person的子女以他們被添加的順序來排列的;但現在你希望以相反的順序列出這些子女。當你編寫另一個for循環,以相反的順序向各個對象添加到一個新的ArrayList中時,代碼在編寫了第三或第四遍之后將變得冗長。
        清單3就是未被利用的算法:

    清單3. ReverseIterator
    public class ReverseIterator
    {
        
    public static void main(String[] args)
        {
            Person ted 
    = new Person("Ted""Neward"39,
                
    new Person("Michael""Neward"16),
                
    new Person("Matthew""Neward"10));

            
    // Make a copy of the List
            List<Person> kids = new ArrayList<Person>(ted.getChildren());
            
    // Reverse it
            Collections.reverse(kids);
            
    // Display it
            System.out.println(kids);
        }
    }

    Collections類有一組這樣的"算法",該類所實現的靜態方法將Collections作為參數,并且提供了完全獨立于任何實現的行為。
    另外,Collections類所示的算法在好的API設計中肯定不會是最終版本--例如,我不希望直接修改這些方法(由集合對象傳入)的內容。你可以為自己編寫定制的算法,這是一件很好的事情,如清單4所示:

    清單4. 簡潔的反轉迭代器
    class MyCollections
    {
        
    public static <T> List<T> reverse(List<T> src)
        {
            List
    <T> results = new ArrayList<T>(src);
            Collections.reverse(results);
            
    return results;
        }
    }

    5. 擴展的集合框架API
        上述定制的算法證明了Java集合API的最后一個問題:Java集合框架一直被設計為是可擴展的,可被改變以去適應開發者的特殊目的。
        例如,假設你需要Person中的children總是按年齡排序。雖然你可以一遍一遍地編寫代碼去對children進行排序(可能會使用 Collections.sort方法),要是有一個集合類能夠幫你作這樣的排序則會好得多。
        實際上,你可能并不關心添加到集合中的對象是以何種順序存儲的(這就是使用List的主要理由),你只是想讓它們保持一定的順序罷了。
        java.util包中沒有哪一個集合類能滿足這些需求,寫一個卻很容易。你所需要做的只是創建一個接口,該接口描述了該集合類需要提供的抽象行為。在 SortedCollection這個例子中,上述意圖是完全可行的。

    清單5. SortedCollection
    public interface SortedCollection<E> extends Collection<E>
    {
        
    public Comparator<E> getComparator();
        
    public void setComparator(Comparator<E> comp);
    }

    基本上是虎頭蛇尾般地寫成了這個新接口的實現:

    清單6. ArraySortedCollection
    import java.util.*;

    public class ArraySortedCollection<E>
        
    implements SortedCollection<E>, Iterable<E>
    {
        
    private Comparator<E> comparator;
        
    private ArrayList<E> list;
            
        
    public ArraySortedCollection(Comparator<E> c)
        {
            
    this.list = new ArrayList<E>();
            
    this.comparator = c;
        }
        
    public ArraySortedCollection(Collection<? extends E> src, Comparator<E> c)
        {
            
    this.list = new ArrayList<E>(src);
            
    this.comparator = c;
            sortThis();
        }

        
    public Comparator<E> getComparator() { return comparator; }
        
    public void setComparator(Comparator<E> cmp) { comparator = cmp; sortThis(); }
        
        
    public boolean add(E e)
        { 
    boolean r = list.add(e); sortThis(); return r; }
        
    public boolean addAll(Collection<? extends E> ec)
        { 
    boolean r = list.addAll(ec); sortThis(); return r; }
        
    public boolean remove(Object o)
        { 
    boolean r = list.remove(o); sortThis(); return r; }
        
    public boolean removeAll(Collection<?> c)
        { 
    boolean r = list.removeAll(c); sortThis(); return r; }
        
    public boolean retainAll(Collection<?> ec)
        { 
    boolean r = list.retainAll(ec); sortThis(); return r; }
        
        
    public void clear() { list.clear(); }
        
    public boolean contains(Object o) { return list.contains(o); }
        
    public boolean containsAll(Collection <?> c) { return list.containsAll(c); }
        
    public boolean isEmpty() { return list.isEmpty(); }
        
    public Iterator<E> iterator() { return list.iterator(); }
        
    public int size() { return list.size(); }
        
    public Object[] toArray() { return list.toArray(); }
        
    public <T> T[] toArray(T[] a) { return list.toArray(a); }
        
        
    public boolean equals(Object o)
        {
            
    if (o == this)
                
    return true;
            
            
    if (o instanceof ArraySortedCollection)
            {
                ArraySortedCollection
    <E> rhs = (ArraySortedCollection<E>)o;
                
    return this.list.equals(rhs.list);
            }
            
            
    return false;
        }
        
    public int hashCode()
        {
            
    return list.hashCode();
        }
        
    public String toString()
        {
            
    return list.toString();
        }
        
        
    private void sortThis()
        {
            Collections.sort(list, comparator);
        }
    }

    這個應急式的實現,未經縝密的思索就寫成了,毫無疑問它需要進行重構。但重點是,對于所有與集合相關的事情中,Java集合框架API原本就不是被設計成不需被修改的。它既需要也鼓勵擴展。
        當然,有一些擴展會是有"重要職責"的變體,例如由java.util.concurrent包引用的擴展實現。但其它的一些則只是簡單地編寫一個定制算法,或是對已有集合類的一個簡單擴展。
        擴展Java集合框架API看起來很具顛覆性,但一旦你開始做了,你就會發現并不如你所想像的那般困難。

    結論
        與Java序列化相同,Java集合框架API滿是未被探究的細微之處--這也是為什么我們沒有結束該主題的原因。5 things系列的下一篇文章將會向你展示使用Java集合框API做更多事情的另外5種方法。

    請關注你所不知道的五件事情--Java集合框架API(第二部分)

    祝大家五·一假期愉快 ^_^

    posted on 2010-05-02 18:21 John Jiang 閱讀(6121) 評論(3)  編輯  收藏 所屬分類: Java翻譯

    評論

    # re: 你所不知道的五件事情--Java集合框架API(第一部分)(譯)[未登錄] 2010-05-08 22:05 cc
    Person ted = new Person("Ted", "Neward", 39,
    new Person("Michael", "Neward", 16),
    new Person("Matthew", "Neward", 10));
    這段明顯跟你的Person構造方法,感覺應該寫個kid(String fn, String ln, int a)來繼承Person對象;
    Person ted = new Person("Ted", "Neward", 39,
    new Kid("Michael", "Neward", 16),
    new Kid("Matthew", "Neward", 10));
    這樣才對吧!  回復  更多評論
      

    # re: 你所不知道的五件事情--Java集合框架API(第一部分)(譯)[未登錄] 2010-05-08 22:19 cc
    其實也就是說一句話:在jdk1.5中,只要我們的類實現了Iterable接口的,即也可以使用如下語句, for(Object o : iterable);

      回復  更多評論
      

    # re: 你所不知道的五件事情--Java集合框架API(第一部分)(譯) 2010-05-08 22:47 Sha Jiang
    @cc
    > 感覺應該寫個kid(String fn, String ln, int a)來繼承Person對象;
    > Person ted = new Person("Ted", "Neward", 39,
    > new Kid("Michael", "Neward", 16),
    > new Kid("Matthew", "Neward", 10));
    我認為不需要創建這個Kid類。
    至少從你的示例沒看出這種"必要性"。實質上,Kid并沒有對Person進行擴展。  回復  更多評論
      

    主站蜘蛛池模板: 午夜免费啪视频在线观看| a级毛片免费观看在线| 最近中文字幕免费mv在线视频| 亚洲午夜未满十八勿入网站2| 国产高潮久久免费观看| 亚洲综合激情另类专区| 毛片基地看看成人免费| 国产亚洲综合网曝门系列| 无码少妇精品一区二区免费动态| 久久精品国产亚洲AV网站| 久久精品视频免费播放| 亚洲色偷偷av男人的天堂| 久久精品免费一区二区| 亚洲 日韩 色 图网站| 国产又黄又爽又猛的免费视频播放 | 亚洲中文字幕无码中文| 成年人免费网站在线观看| 亚洲av色香蕉一区二区三区蜜桃| 亚洲AV无码之日韩精品| a级片在线免费看| 在线观看亚洲人成网站| 成年女人毛片免费视频| 永久免费无码日韩视频| 久久亚洲综合色一区二区三区| 久久久久av无码免费网| 亚洲乱亚洲乱妇24p| 亚洲国产精品一区二区九九| 视频免费在线观看| 亚洲六月丁香六月婷婷蜜芽| 国产一区二区三区免费在线观看| 三年片免费观看大全国语| 91亚洲国产成人久久精品| 免费永久看黄在线观看app| 在线观看肉片AV网站免费| 亚洲一级在线观看| 国产精品亚洲mnbav网站 | 亚洲国产综合精品中文字幕| 精品国产免费一区二区三区香蕉| 亚洲一区精品视频在线| 亚洲性在线看高清h片| 国产在线观看麻豆91精品免费 |