程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> JAVA綜合教程 >> Java編程手冊-Collection框架(上)

Java編程手冊-Collection框架(上)

編輯:JAVA綜合教程

Java編程手冊-Collection框架(上)


該文章所講內容基本涵蓋了Collection裡面的所有東西,雖然基於jdk 1.5的,但是思路很清晰

1.引言
1.1 Collection框架的介紹

雖然我們可以使用數組去存儲具有相同類型的元素集合(包括基本類型和對象類型),但是數組不支持所謂的動態內存分配,一旦分配之後,它的長度就是固定的,無法改變,另外,數組是一個簡單的線性結構,在我們的實際開發中,可能會需要更復雜的數據結構,例如linked list, stack, hash table, sets, 或者 trees.

在Java中,有統一的Collection框架來支持這種動態分配的數據結構(例如:ArrayList, LinkedList, Vector, Stack, HashSet, HashMap, Hashtable),它通過接口統一了所有繼承類的基本操作,形成了一套基本的體系。

Java集合框架包(java.util)裡包含下面內容:

1、接口集合
2、類實現
3、算法(例如排序和查找)

1.2 Colloction例子- ArrayList (Pre-JDK 1.5)

ArrayList是一個線性的數據結構,類似於數組,但是它是可伸縮的。下面使用了ArrayList來存放String集合對象。

 

// Pre-JDK 1.5
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
 
public class ArrayListPreJDK15Test {
   public static void main(String[] args) {
      List lst = new ArrayList();  // A List contains instances of Object. Upcast ArrayList to List
      lst.add("alpha");            // add() takes Object. String upcast to Object implicitly
      lst.add("beta");
      lst.add("charlie");
      System.out.println(lst);     // [alpha, beta, charlie]
 
      // Get a "iterator" instance from List to iterate thru all the elements of the List
      Iterator iter = lst.iterator();
      while (iter.hasNext()) {      // any more element
         // Retrieve the next element, explicitly downcast from Object back to String
         String str = (String)iter.next();
         System.out.println(str);
      }
   }
}

程序分析

 

2-4行引入了java.util包中集合框架的類和接口 \  

 

上圖可以看到ArrayList的繼承關系,我們可以看到ArrayList實現了List, Collection 和 Iterable接口,Collection和Iterable接口定義了所有集合都需要實現的基本操作。Collection接口定義了如何添加和移除一個元素。Iterable接口定義了一種機制去遍歷集合中的所有元素。一般不直接使用Collection接口,而是使用它的子接口List(支持索引訪問的有序列表)、Set(不允許元素的重復)、Queue(先進先出)。

 

在第8行中,創建了一個ArrayList實例,並將它向上轉換為List接口,因為ArrayList實現了List接口,一般比較良好的編程操作都是在接口上面,而不是在它的實現上面。Collection框架提供了一個接口集合,這樣你可以使用這些接口而不是它的實現。
Collection接口定義了一些對基本的操作方法。
// Pre-JDK 1.5
boolean add(Object element)     // adds an element
boolean remove(Object element)  // removes an element
int size()                      // returns the size
boolean isEmpty()               // checks if empty
可以看到,在pre-JDK 1.5上,add(Object)方法操作的是Object對象,Object類是所有類的超類,因此,所有類都是Object類的子類,任何Java類都可以向上轉換為Object類,然後添加到集合中,並且這個轉換是編譯器隱式操作的,它是類型安全的。 Iterable接口包含一個抽象方法去獲取集合所關聯的Iterator對象,這樣通過Iterator對象就可以遍歷整個集合。
Iterator iterator();   // returns an Iterator object to iterate thru all the elements of the collection
Iterator聲明了下面的抽象方法進行集合遍歷
// Pre-JDK 1.5
boolean hasNext()  // returns true if it has more elements
Object next()      // returns the next element
void remove()      // removes the last element returned by the iterator
第15-20行獲取ArrayList相關聯的Iterator對象,並且使用while循環來遍歷集合。
在18行,iter.next()方法方法返回的是Object類型的對象,這個在上面add(Object)中說過,我們在得到Object類型的對象之後,需要顯式的將類型轉換為String類型,因為編譯器不知道我們需要的具體類型。其實我們也可以使用LinkedList, Vector 和 Stack,並且只需要修改第8行的實例化代碼即可,其他不變,這也可以看出接口的統一性,雖然實現不同,但是操作的效果相同。
List lst = new LinkedList();   // use "LinkedList" implementation
// or
List lst = new Vector();       // use "Vector" implementation
// or
List lst = new Stack();        // use "Stack" implementation

1.3 Pre-JDK 1.5 Collections不是類型安全的 Pre-JDK 1.5存在下面的缺陷: 1、編譯器會將元素隱式地向上轉換為java.lang.Object,但是當我們獲取元素的時候,我們獲取的就是java.lang.Object類型的對象,我們需要顯式的將它向下轉換為我們的原始類型。
2、編譯器不能在編譯時檢查向下轉換的有效性,錯誤的向下轉換會在運行是拋出ClassCastException異常。 這兩個問題其實在上面代碼的分析過程中也說到過,缺陷也很明顯。
// lst is designed to hold Strings
lst.add(new Integer(88));  // adds an Integer, implicitly upcast to Object, okay in compile/runtime
 
Iterator iter = lst.iterator();
while (iter.hasNext()) {
   String str = (String)iter.next(); // compile okay but runtime ClassCastException
   System.out.println(str);
}

1.4 JDK 1.5中引入泛型 針對上面的缺陷,JDK 1.5中引入了一個新的特性——泛型,它可以傳遞類型信息,這樣編譯器在編譯的過程中可以進行必要的類型檢查,這樣就避免的運行是類型安全問題。
List lst = new ArrayList();  // read as List of Strings, ArrayList of Strings
上面我們傳遞了一個String類型,在ArrayList內部的操作使用的就是String類型,避免了類型的轉換,如果添加其他類型的元素,編譯器就會報錯。   1.5 帶有泛型的ArrayList
// Post-JDK 1.5 with Generics
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
 
public class ArrayListPostJDK15Test {
   public static void main(String[] args) {
      List lst = new ArrayList();  // Inform compiler about the type
      lst.add("alpha");         // compiler checks if argument's type is String
      lst.add("beta");
      lst.add("charlie");
      System.out.println(lst);  // [alpha, beta, charlie]
 
      Iterator iter = lst.iterator();   // Iterator of Strings
      while (iter.hasNext()) {
         String str = iter.next();  // compiler inserts downcast operator
         System.out.println(str);
      }
 
//      lst.add(new Integer(1234));   // ERROR: compiler can detect wrong type
//      Integer intObj = lst.get(0);  // ERROR: compiler can detect wrong type
 
      // Enhanced for-loop (JDK 1.5)
      for (String str : lst) {
         System.out.println(str);
      }
   }
}

可以看到,使用泛型之後,就基本不存在前面所說隱式和顯式類型轉換了,因為內部使用的就是我們傳遞進去的類型,而不是上面所說的Object類型,如果添加其他類型的話,編譯器就會報錯。   1.6 向後兼容
JDK 1.5是兼容pre-JDK 1.5的使用的。例如在JDK 1.5中使用pre-JDK 1.5的用法,仍然是可以執行的,只是同樣沒有類型檢查。
// Pre-JDK 1.5
List lst = new ArrayList();  // No type information
lst.add("alpha");   // Without generics, compiler can't check if the type is correct

1.7 自動裝箱和自動拆箱(JDK 1.5) 一個集合只能存放對象,它不能包含基本數據類型,例如int或者double,這就存在問題了,盡管數組可以存放基本數據類型,但是前面說過它是不可擴展的。所以如果希望在集合中存放基本數據類型,就必須使用對應的包裝類把基本數據類型包裝成對應類型的對象,下面這副圖對應的就是基本數據類型與對象類型的對應關系。 \     在JDK 1.5之前,向集合添加元素,必須將基本數據類型包裝為對應的對象類型,從集合獲取元素,必須把對應對象類型拆解為對應的基本數據類型。
// Pre-JDK 1.5
Integer intObj = new Integer(5566);    // wrap int to Integer
int i = intObj.intValue();             // unwrap Integer to int
 
Double doubleObj = new Double(55.66);  // wrap double to Double
double d = doubleObj.doubleValue();    // unwrap Double to double

從上面可以看到,在JDK 1.5之前,裝箱和解箱操作需要我們自己手動去完成,JDK 1.5就針對這一問題,提出了一個新特性,就是自動裝箱與解箱。也就是本來需要我們手工完成的事情,編譯器幫助我們完成了。
// JDK 1.5
Integer intObj = 5566;    // autobox from int to Integer
int i = intObj;           // auto-unbox from Integer to int
 
Double doubleObj = 55.66; // autoboxing from double to Double
double d = doubleObj;     // atuo-unbox from Double to double

例子—Pre JDK 1.5中集合 Pre JDK 1.5不支持泛型、自動裝箱與解箱和for-each循環,下面的代碼就顯得混亂並且不是類型安全的。
// Pre-JDK 1.5
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
 
public class PrimitiveCollectionPreJDK15 {
   public static void main(String[] args) {
      List lst = new ArrayList();
 
      // Add 10 random primitive int into the List
      Random random = new Random();
      for (int i = 1; i <= 10; ++i) {
         // Wrap the primitive int into Integer, upcast to Object
         lst.add(new Integer(random.nextInt(10)));
      }
      System.out.println(lst);
 
      Iterator iter = lst.iterator();
      while (iter.hasNext()) {
         // Explicit downcast to Integer, then unwrap to int
         int i = ((Integer)iter.next()).intValue();   // un-safe at runtime
         System.out.println(i);
      }
   }
}

例子-Post-JDK 1.5中的集合 在JDK1.5之後,就支持了泛型、自動裝箱與解箱以及for-each循環,代碼會更加簡潔並且是類型安全的。
// Post-JDK 1.5
import java.util.List;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Random;
 
public class PrimitiveCollectionJDK15 {
   public static void main(String[] args) {
      List lst = new ArrayList();
 
      // Add 10 random primitive int into the List
      Random random = new Random();
      for (int i = 1; i <= 10; ++i) {
         lst.add(random.nextInt(10)); // autobox to Integer, upcast to Object, type-safe
      }
      System.out.println(lst);
 
      // Transverse via iterator
      Iterator iter = lst.iterator();
      while (iter.hasNext()) {
         int i = iter.next();  // downcast to Integer, auto-unbox to int, type-safe
         System.out.println(i);
      }
 
      // Transverse via enhance for-loop
      for (int i : lst) {      // downcast to Integer, auto-unbox to int, type-safe
         System.out.println(i);
      }
 
      // Retrieve via for-loop with List's index
      for (int i = 0; i < lst.size(); ++i) {
         int j = lst.get(i);   // downcast to Integer, auto-unbox to int, type-safe
         System.out.println(j);
      }
   }
}

2. Collection接口 下圖是Collection框架中的接口和常用實現類 \

 

 

2.1 Iterable接口

Iterable接口,它包含了一個泛型類型E,E對應的就是集合元素類型,這個接口聲明了一個抽象方法iterator()用來獲取一個Iterator對象,Iterator用來遍歷它所關聯集合的所有元素。

 

Iterator iterator();   // Returns the associated Iterator instance 
                          // that can be used to transverse thru all the elements of the collection
所有Collection的實現(例如:ArrayList,LinkedList,Vector)必須實現這個方法,並且返回的對象也實現了Iterator接口。

 

2.2 Iterator接口

Iterator接口聲明了下面三個抽象方法。

 

boolean hasNext()  // Returns true if it has more elements
E next()           // Returns the next element of generic type E
void remove()      // Removes the last element returned by the iterator

我們可以使用Iterator和一個while循環進行集合的遍歷

 

 

List lst = new ArrayList();
lst.add("alpha");
lst.add("beta");
lst.add("charlie");
 
// Retrieve the Iterator associated with this List via the iterator() method
Iterator iter = lst.iterator();
// Transverse thru this List via the Iterator
while (iter.hasNext()) {
   // Retrieve each element and process
   String str = iter.next();
   System.out.println(str);
}

2.3 加強版的for循環 (JDK 1.5)

 

對於使用Iterator進行集合的遍歷,在JDK 1.5中引入了新的加強版的for循環,使用它進行集合的遍歷更加方便。

下面是基本的用法

 

for ( type item : aCollection ) {
   body ;
}

可以在集合中修改對象嗎?

 

加強版的for循環提供了一個方便的方法去遍歷集合元素,但是它將Iterator給隱藏了,因此你不能移除或者替換這個元素。循環變量接受的是一個引用的副本,因此這個加強版的for循環可以通過該引用修改對應的可變元素(例如:StringBuilder),但是不能修改不可變元素(例如:String和基本數據類型對應的對象類型)。

例子——使用加強版的for循環對於集合的可變元素(例如:StringBuilder)

 

import java.util.List;
import java.util.ArrayList;
 
public class ForEachMutableTest {
   public static void main(String[] args) {
      List lst = new ArrayList();
      lst.add(new StringBuilder("alpha"));
      lst.add(new StringBuilder("beta"));
      lst.add(new StringBuilder("charlie"));
      System.out.println(lst);   // [alpha, beta, charlie]
 
      for (StringBuilder sb : lst) {
         sb.append("88");   // can modify "mutable" objects
      }
      System.out.println(lst);  // [alpha88, beta88, charlie88]
   }
}

例子——使用加強版的for循環對於集合的不可變元素(例如:StringBuilder)

 

 

import java.util.List;
import java.util.ArrayList;
 
public class ForEachImmutableTest {
   public static void main(String[] args) {
      List lst = new ArrayList();
      lst.add("alpha");
      lst.add("beta");
      lst.add("charlie");
      System.out.println(lst);   // [alpha, beta, charlie]
 
      for (String str : lst) {
         str += "change!";   // cannot modify "immutable" objects
      }
      System.out.println(lst);   // [alpha, beta, charlie]
   }
}

2.4 Collection接口

 

Collection包含一個泛型類型E,E是集合的元素數據類型,並且Collection是集合框架的超類,它包含了其他類都需要實現的基本操作,例如:

 

// Basic Operations
int size()                        // Returns the number of elements of this Collection
void clear()                      // Removes all the elements of this Collection
boolean isEmpty()                 // Returns true if there is no element in this Collection
boolean add(E element)            // Ensures that this Collection contains the given element
boolean remove(Object element)    // Removes the given element, if present
boolean contains(Object element)  // Returns true if this Collection contains the given element

// Bulk Operations with another Collection
boolean containsAll(Collection c)       // Collection of any "unknown" object
boolean addAll(Collection c)  // Collection of E or its sub-types
boolean removeAll(Collection c)
boolean retainAll(Collection c)
 
// Comparison - Objects that are equal shall have the same hashCode
boolean equals(Object o)
int hashCode()
 
// Array Operations
Object[] toArray()       // Convert to an Object array
 T[] toArray(T[] a)   // Convert to an array of the given type T

Collection中只能包含對象類型,不能包含基本數據類型(例如:int和double),所以如果需要將基本數據類型包裝成對應的對象類型,JDK 1.5引入了自動拆箱和解箱操作來解決這個問題,這個在前面已經講過。

 

2.5 List, Set & Queue —— Collection的子接口

在實際開發過程中,我們一般使用Collection的子類接口——List,Set, 和Queue,它們提供了更多其他的特性。

 

List:它相當於一個可擴展的線性數組,可以進行索引訪問,並且可以包含重復的元素,我們經常會使用到的一些List的實現類為:ArrayList,LinkedList,VectorStack。
Set:相當於一個數據集合,它不能包含重復的元素,經常使用到的Set的實現類為:HashSet和LinkedHashSet,子接口為SortedSet是一個有序的元素集合,TreeSet是SortedSet的實現類。
Queue: 相當於一個先進先出的隊列,它的子接口Deque相當於一個可在兩端操作的雙向隊列,實現類為PriorityQueue,ArrayDequeLinkedList。 2.6 Map接口 接口Map包含了兩個泛型類型K和V,它們組成一個鍵值對,Map就是一個鍵值對的集合,鍵值key是不允許重復的,經常使用到的實現類為HashMap,HashtableLinkedHashMap,它的子接口SortedMap表示一個基於鍵值key有序的鍵值對集合,實現類為TreeMap。   需要注意的是,Map不是Collection的子接口。   3. List接口與實現 在實際的編程中,我們更多使用的是Collection的子接口List,Set, 和Queue來代替Collection接口,這些子接口只是對Collection接口操作的重新定義。 List相當於一個可擴展的線性數組,它支持索引訪問,它可以包含重復的元素,也可以包含null元素。 \   在List父接口的基礎上,List也聲明了一些抽象方法。
// Operations at a specified index position
void add(int index, E element)    // add
E set(int index, E element)       // replace
E get(int index)                  // retrieve without remove
E remove(int index)               // remove last retrieved
int indexOf(Object obj)
int lastIndexOf(Object obj)
// Operations on a range fromIndex (inclusive) toIndex (exclusive)
List subList(int fromIndex, int toIndex)
......
 
// Operations inherited from Collection
int size()
boolean isEmpty()
boolean add(E element)
boolean remove(Object obj)
boolean contains(Object obj)
void clear();
......

抽象類AbstractList提供了很多List、Collector和Iterable接口中聲明的抽象方法的實現,另外有些方法仍然是抽象的,這些方法會被子類實現,例如ArrayListVector。   3.1 ArrayList & Vector - List的實現類 ArrayList是List接口全面的實現類,很多有用的方法已經被AbstractList實現,但是ArrayList也進行了重寫。ArrayList不是線程同步的,因此它不是線程安全的。 Vector是JDK 1.0中遺留的類,在JDK 1.2中將它更新到了Collection中,它是List接口的一個線程同步(線程安全)的實現,包含了很多遺留的方法(例如:addElement(),removeElement(),setElement(),elementAt(),firstElement(),lastElement(),insertElementAt()),毫無疑問,這些遺留的方法是可以使用的,並且保持向後兼容。 需要注意的是,雖然ArrayList不是線程安全的,而Vector是線程安全的,但是ArrayList顯然比Vector有更好的性能。   3.2 Stack - List的實現類 Stack是一個後進先出的隊列,它擴展於Vector,它是一個同步的可擴展的數組,也就是它是線程安全的,包含了下面方法。
E push(E element)       // pushes the specified element onto the top of the stack
E pop()                 // removes and returns the element at the top of the stack
E peek()                // returns the element at the top of stack without removing
boolean empty()         // tests if this stack is empty
int search(Object obj)  // returns the distance of the specified object from the top
                        //  of stack (distance of 1 for TOS), or -1 if not found

3.3 LinkedList - List的實現類 LinkedList是一個雙向鏈表,它實現了List接口,在元素的插入和刪除上,效率更高,但是浪費了更多復雜的結構。 LinkedList也實現了QueueDeque,因此它可以充當FIFO 和 LIFO隊列。   3.4 轉換一個List為一個數組 - toArray() 在超類接口Collection中定義了一個toArray()方法,它可以使用該列表來創建一個數組,返回的數組可以進行自由的修改。
Object[] toArray()      // Object[] version
 T[] toArray(T[] a)  // Generic type version

例子:
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
public class TestToArray {
   public static void main(String[] args) {
      List lst = new ArrayList();
      lst.add("alpha");
      lst.add("beta");
      lst.add("charlie");
 
      // Use the Object[] version
      Object[] strArray1 = lst.toArray();
      System.out.println(Arrays.toString(strArray1));   // [alpha, beta, charlie]
 
      // Use the generic type verion - Need to specify the type in the argument
      String[] strArray2 = lst.toArray(new String[0]);
      strArray2[0] = "delta";   // modify the returned array
      System.out.println(Arrays.toString(strArray2));   // [delta, beta, charlie]
      System.out.println(lst);  // [alpha, beta, charlie] - no change in the original list
   }
}

3.5 將數組轉換為一個List - Arrays.asList() 工具類java.util.Arrays提供了靜態方法Arrays.asList()可以將數組轉換為List,但是,如果修改了List裡面的元素內容,數組中相應的元素內容也會改變,反之亦然。   例子:
import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
public class TestArrayAsList {
   public static void main(String[] args) {
      String[] strs = {"alpha", "beta", "charlie"};
      System.out.println(Arrays.toString(strs));   // [alpha, beta, charlie]
 
      List lst = Arrays.asList(strs);
      System.out.println(lst);  // [alpha, beta, charlie]
 
      // Changes in array or list write thru
      strs[0] += "88";
      lst.set(2, lst.get(2) + "99");
      System.out.println(Arrays.toString(strs)); // [alpha88, beta, charlie99]
      System.out.println(lst);  // [alpha88, beta, charlie99]
 
      // Initialize a list using an array
      List lstInt = Arrays.asList(22, 44, 11, 33);
      System.out.println(lstInt);  // [22, 44, 11, 33]
   }
}

3.6 ArrayList, Vector, LinkedList 和 Stack的比較   4. 排序與查找 使用Collections.sort()Arrays.sort()可進行排序
有些集合,例如SortedSet(TreeSet) 和SortMap(TreeMap)是有序的 有兩種方法進行排序: 是對象實現java.lang.Comparable,重寫compareTo()方法去指定兩個對象的排序方法。創建一個指定的java.util.Comparator對象,實現compare()方法去指定兩個對象的比較。 4.1 java.lang.Comparable接口 java.lang.Comparable可以指定兩個對象如何進行比較,它定義了一個抽象方法。
int compareTo(T o)  // Returns a negative integer, zero, or a positive integer 
                    // as this object is less than, equal to, or greater than the given object

一般推薦compareTo()方法與equals()hashCode()是一致的,即: 如果compareTo()返回0,那麼equals()應該返回true。如果equals()返回true,那麼hashCode()應該返回的是相同的int值。 所有基本數據類型的包裝類(例如:Byte,Short,Integer,Long,Float,Double,CharacterandBoolean)都實現了Comparable接口的compareTo()方法。   例子: 工具類java.util.Arraysjava.util.Collections對應不同的算法提供了很多的靜態方法,例如排序和查找。 在下面這個例子中,使用Arrays.sort()Collections.sort()方法去對一個String數組和一個Integer的List進行排序,使用的就是它們默認的Comparable實現。
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
 
public class TestComparable {
   public static void main(String[] args) {
      // Sort and search an "array" of Strings
      String[] array = {"Hello", "hello", "Hi", "HI"};
 
      // Use the Comparable defined in the String class
      Arrays.sort(array);
      System.out.println(Arrays.toString(array));  // [HI, Hello, Hi, hello]
 
      // Try binary search - the array must be sorted
      System.out.println(Arrays.binarySearch(array, "Hello")); // 1
      System.out.println(Arrays.binarySearch(array, "HELLO")); // -1 (insertion at index 0)
 
      // Sort and search a "List" of Integers
      List lst = new ArrayList();
      lst.add(22);  // auto-box
      lst.add(11);
      lst.add(44);
      lst.add(33);
      Collections.sort(lst);    // Use the Comparable of Integer class
      System.out.println(lst);  // [11, 22, 33, 44]
      System.out.println(Collections.binarySearch(lst, 22)); // 1
      System.out.println(Collections.binarySearch(lst, 35)); // -4 (insertion at index 3)
   }
}
4.2 java.util.Comparator 接口
在Comparable之外,我們可以傳遞一個Comparator對象到排序方法中(Collections.sort()Arrays.sort())來實現大小比較,如果Comparator可用,那麼Comparator將會重寫Comparable。
int compare(T o1, T o2)    // Returns a negative integer, zero, or a positive integer as the 
                           // first argument is less than, equal to, or greater than the second.
  需要注意的是,你需要創建Comparator實例,並且實現compare()方法去進行對象的比較,在Comparable中,只需要調用對象的compareTo()方法,它只需要傳遞一個參數,表示當前對象和另一個對象比較,在Comparator需要傳遞兩個參數,表示兩個對象的比較。   例子
import java.util.Arrays;
import java.util.List;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
 
public class TestComparator {
 
   // Define a Comparator to order strings in case-insensitive manner
   public static class StringComparator implements Comparator {
      @Override
      public int compare(String s1, String s2) {
         return s1.compareToIgnoreCase(s2);
      }
   }
 
   // Define a Comparator to order Integers based on the least significant digit
   public static class IntegerComparator implements Comparator {
      @Override
      public int compare(Integer s1, Integer s2) {
         return s1%10 - s2%10;
      }
   }
 
   public static void main(String[] args) {
      // Use a customized Comparator for Strings
      Comparator compStr = new StringComparator();
 
      // Sort and search an "array" of Strings
      String[] array = {"Hello", "Hi", "HI", "hello"};
      Arrays.sort(array, compStr);
      System.out.println(Arrays.toString(array));  // [Hello, hello, Hi, HI]
      System.out.println(Arrays.binarySearch(array, "Hello", compStr)); // 1
      System.out.println(Arrays.binarySearch(array, "HELLO", compStr)); // 1 (case-insensitive)
 
      // Use a customized Comparator for Integers
      Comparator compInt = new IntegerComparator();
 
      // Sort and search a "List" of Integers
      List lst = new ArrayList();
      lst.add(42);  // auto-box
      lst.add(21);
      lst.add(34);
      lst.add(13);
      Collections.sort(lst, compInt);
      System.out.println(lst);  // [21, 42, 13, 34]
      System.out.println(Collections.binarySearch(lst, 22, compInt)); // 1
      System.out.println(Collections.binarySearch(lst, 35, compInt)); // -5 (insertion at index 4)
   }
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved