乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      關(guān)于 Java Collections API 您可能不知道的 5 件事

       昵稱(chēng)5370487 2011-01-04

      對(duì)于很多 Java 開(kāi)發(fā)人員來(lái)說(shuō),Java Collections API 是標(biāo)準(zhǔn) Java 數(shù)組及其所有缺點(diǎn)的一個(gè)非常需要的替代品。將 Collections 主要與 ArrayList 聯(lián)系到一起本身沒(méi)有錯(cuò),但是對(duì)于那些有探索精神的人來(lái)說(shuō),這只是 Collections 的冰山一角。

      雖然 Map(以及它的常用實(shí)現(xiàn) HashMap)非常適合名-值對(duì)或鍵-值對(duì),但是沒(méi)有理由讓自己局限于這些熟悉的工具??梢允褂眠m當(dāng)?shù)?API,甚至適當(dāng)?shù)?Collection 來(lái)修正很多易錯(cuò)的代碼。

      1. Collections 比數(shù)組好

      剛接觸 Java 技術(shù)的開(kāi)發(fā)人員可能不知道,Java 語(yǔ)言最初包括數(shù)組,是為了應(yīng)對(duì)上世紀(jì) 90 年代初期 C++ 開(kāi)發(fā)人員對(duì)于性能方面的批評(píng)。從那時(shí)到現(xiàn)在,我們已經(jīng)走過(guò)一段很長(zhǎng)的路,如今,與 Java Collections 庫(kù)相比,數(shù)組不再有性能優(yōu)勢(shì)。

      例如,若要將數(shù)組的內(nèi)容轉(zhuǎn)儲(chǔ)到一個(gè)字符串,需要迭代整個(gè)數(shù)組,然后將內(nèi)容連接成一個(gè) String;而 Collections 的實(shí)現(xiàn)都有一個(gè)可用的 toString() 實(shí)現(xiàn)。

      除少數(shù)情況外,好的做法是盡快將遇到的任何數(shù)組轉(zhuǎn)換成集合。于是問(wèn)題來(lái)了,完成這種轉(zhuǎn)換的最容易的方式是什么?事實(shí)證明,Java Collections API 使這種轉(zhuǎn)換變得容易,如清單 1 所示:

      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 是不可修改的,所以如果嘗試向其中添加新元素將拋出一個(gè) UnsupportedOperationException

      而且,由于 Arrays.asList() 使用 varargs 參數(shù)表示添加到 List 的元素,所以還可以使用它輕松地用以 new 新建的對(duì)象創(chuàng)建 List。

      2. 迭代的效率較低

      將一個(gè)集合(特別是由數(shù)組轉(zhuǎn)化而成的集合)的內(nèi)容轉(zhuǎn)移到另一個(gè)集合,或者從一個(gè)較大對(duì)象集合中移除一個(gè)較小對(duì)象集合,這些事情并不鮮見(jiàn)。

      您也許很想對(duì)集合進(jìn)行迭代,然后添加元素或移除找到的元素,但是不要這樣做。

      在此情況下,迭代有很大的缺點(diǎn):

      • 每次添加或移除元素后重新調(diào)整集合將非常低效。
      • 每次在獲取鎖、執(zhí)行操作和釋放鎖的過(guò)程中,都存在潛在的并發(fā)困境。
      • 當(dāng)添加或移除元素時(shí),存取集合的其他線程會(huì)引起競(jìng)爭(zhēng)條件。

      可以通過(guò)使用 addAllremoveAll,傳入包含要對(duì)其添加或移除元素 的集合作為參數(shù),來(lái)避免所有這些問(wèn)題。

      3. 用 for 循環(huán)遍歷任何 Iterable

      Java 5 中加入 Java 語(yǔ)言的最大的便利功能之一,增強(qiáng)的 for 循環(huán),消除了使用 Java 集合的最后一道障礙。

      以前,開(kāi)發(fā)人員必須手動(dòng)獲得一個(gè) Iterator,使用 next() 獲得 Iterator 指向的對(duì)象,并通過(guò) hasNext() 檢查是否還有更多可用對(duì)象。從 Java 5 開(kāi)始,我們可以隨意使用 for 循環(huán)的變種,它可以在幕后處理上述所有工作。

      實(shí)際上,這個(gè)增強(qiáng)適用于實(shí)現(xiàn) Iterable 接口的任何對(duì)象,而不僅僅是 Collections。

      清單 2 顯示通過(guò) Iterator 提供 Person 對(duì)象的孩子列表的一種方法。 這里不是提供內(nèi)部 List 的一個(gè)引用 (這使 Person 外的調(diào)用者可以為家庭增加孩子 — 而大多數(shù)父母并不希望如此),Person 類(lèi)型實(shí)現(xiàn) Iterable。這種方法還使得 for 循環(huán)可以遍歷所有孩子。

      // 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());
              }
          }
      }
      在域建模的時(shí)候,使用 Iterable 有一些明顯的缺陷,因?yàn)橥ㄟ^(guò) iterator() 方法只能那么 “隱晦” 地支持一個(gè)那樣的對(duì)象集合。但是,如果孩子集合比較明顯,Iterable 可以使針對(duì)域類(lèi)型的編程更容易,更直觀。

      4. 經(jīng)典算法和定制算法

      您是否曾想過(guò)以倒序遍歷一個(gè) Collection?對(duì)于這種情況,使用經(jīng)典的 Java Collections 算法非常方便。

      在上面的代碼中,Person 的孩子是按照傳入的順序排列的;但是,現(xiàn)在要以相反的順序列出他們。雖然可以編寫(xiě)另一個(gè) for 循環(huán),按相反順序?qū)⒚總€(gè)對(duì)象插入到一個(gè)新的 ArrayList 中,但是 3、4 次重復(fù)這樣做之后,就會(huì)覺(jué)得很麻煩。

      在此情況下,清單 3 中的算法就有了用武之地:

      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 類(lèi)有很多這樣的 “算法”,它們被實(shí)現(xiàn)為靜態(tài)方法,以 Collections 作為參數(shù),提供獨(dú)立于實(shí)現(xiàn)的針對(duì)整個(gè)集合的行為。

      而且,由于很棒的 API 設(shè)計(jì),我們不必完全受限于 Collections 類(lèi)中提供的算法 — 例如,我喜歡不直接修改(傳入的 Collection 的)內(nèi)容的方法。所以,可以編寫(xiě)定制算法是一件很棒的事情,例如清單 4 就是一個(gè)這樣的例子:

      class MyCollections
      {
          public static <T> List<T> reverse(List<T> src)
          {
              List<T> results = new ArrayList<T>(src);
              Collections.reverse(results);
              return results;
          }
      }

       

      5. 擴(kuò)展 Collections API

      以上定制算法闡釋了關(guān)于 Java Collections API 的一個(gè)最終觀點(diǎn):它總是適合加以擴(kuò)展和修改,以滿(mǎn)足開(kāi)發(fā)人員的特定目的。

      例如,假設(shè)您需要 Person 類(lèi)中的孩子總是按年齡排序。雖然可以編寫(xiě)代碼一遍又一遍地對(duì)孩子排序(也許是使用 Collections.sort 方法),但是通過(guò)一個(gè) Collection 類(lèi)來(lái)自動(dòng)排序要好得多。

      實(shí)際上,您甚至可能不關(guān)心是否每次按固定的順序?qū)?duì)象插入到 Collection 中(這正是 List 的基本原理)。您可能只是想讓它們按一定的順序排列。

      java.util 中沒(méi)有 Collection 類(lèi)能滿(mǎn)足這些需求,但是編寫(xiě)一個(gè)這樣的類(lèi)很簡(jiǎn)單。只需創(chuàng)建一個(gè)接口,用它描述 Collection 應(yīng)該提供的抽象行為。對(duì)于 SortedCollection,它的作用完全是行為方面的。

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

      編寫(xiě)這個(gè)新接口的實(shí)現(xiàn)簡(jiǎn)直不值一提:

      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);
          }
      }
      這個(gè)實(shí)現(xiàn)非常簡(jiǎn)陋,編寫(xiě)時(shí)并沒(méi)有考慮優(yōu)化,顯然還需要進(jìn)行重構(gòu)。但關(guān)鍵是 Java Collections API 從來(lái)無(wú)意將與集合相關(guān)的任何東西定死。它總是需要擴(kuò)展,同時(shí)也鼓勵(lì)擴(kuò)展。

      當(dāng)然,有些擴(kuò)展比較復(fù)雜,例如 java.util.concurrent 中引入的擴(kuò)展。但是另一些則非常簡(jiǎn)單,只需編寫(xiě)一個(gè)定制算法,或者已有 Collection 類(lèi)的簡(jiǎn)單的擴(kuò)展。

      擴(kuò)展 Java Collections API 看上去很難,但是一旦開(kāi)始著手,您會(huì)發(fā)現(xiàn)遠(yuǎn)不如想象的那樣難。

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶(hù) 評(píng)論公約

        類(lèi)似文章 更多