首页 > 代码库 > Java&&持有对象(容器小结)

Java&&持有对象(容器小结)

如果一个程序只包含固定数量的且其生命期都是已知的对象,那么这是一个非常简单的程序。

-------<Thinking in Java>

通常,程序总是根据运行时才知道的某些条件去创建新对象。对象数量,对象类型尚且不能确定。为了解决这个问题,满足程序员需要在任意时刻和任意位置创建任意数量对象的要求。Java实用类库提供了一套相当完整的容器类来解决这个问题(因为数组受到固定尺寸的左右)。其中基本的类型是List,Set,Queue和Map。这些对象类型也称为集合类,但由于java的类库中实用了collection这个名字来指代类库的一个特殊子集,所以我使用了范围更广的术语“容器”称呼他们。

11.1 泛型和类型安全的容器

       要想定义用来保存Apple对象的ArrayList,你可以申明ArrayList<Apple>,而不仅仅只是ArrayList,其中尖括号括起来的是类型参数(可以有多个),它指定了这个容器实例可以保存的类型。此时将元素从List中取出来时,类型转换也不再是必须的了。因为List知道它保存的是什么类型,因此它会在get()时替你执行转型。

11.2 基本概念

        容器类类型库的用途是“保存对象”,并将其划分为两个不同的概念:

        1)Collection:一个独立元素的序列,这些元素都服从一条或多条规则。

         2)Map:一组成对的“键值对”对象,允许你使用键来查找值。

 

名称

类型

实现

优点

缺点

排序

可重复

迭代性

同步

Iterable

接口

 

 

 

F

T

T

F

Collection

接口

 

 

 

F

T

T

F

Queue

接口

 

 

 

F

T

T

F

PriorityQueue

 

堆(一种二叉树)

优先级队列

T

T

T

F

List

接口

按索引排序

 

 

T

T

T

F

LinkedList

双向循环链表

 

 

T

T

T

F

ArrayList

数组

查找

增删

T

T

T

F

Vector

数组

增删

查找

T

T

T

T

Stack

 

 

T

T

T

T

Set

接口

 

 

 

F

F

T

F

TreeSet

 

 

 

T

F

T

F

HashSet

 

 

 

F

F

T

F

Map

接口

 

 

 

F

F

T

F

HashMap

 

查找

 

F

F

T

F

TreeMap

 

排序

 

T

F

T

F

HashTable

 

 

 

 

F

F

T

T

Properties

 

HashTable的子类,表示了一个持久的属性集。


11.2.1 Collection接口(省略常用的方法)

[java] view plaincopy
  1. boolean add(Object obj) 添加一个Object元素  
  2. boolean addAll(Collection c)  
  3. boolean contains(Object obj)  判断obj是否是调用类集的一个元素(属于)  
  4. boolean containsAll(Collection c)  判断c是否是调用类集的子集(包含)  
  5. boolean equals(Collection c) 判断c是否与调用类集相等  
  6. int hashCode() 返回调用类集的hash码  
  7. Iterator iterator() 返回调用类集的迭代程序  
  8. boolean removeAll(Collection c) 从调用类集中去掉所有c中包含的元素(差集)  
  9. boolean retainAll(Collection c) 从调用类集中去掉包含在c中以外的元素(补集)  
  10. Object[] toArray() 返回类集的元素组成的数组  
  11.    
  12. void clear()  
  13. boolean isEmpty()  
  14. int size()  
  15.   
  16. //类集包含一个add(Object obj)方法,因此可以包含任意Object数据,但是不能直接存储:int,char,double等数据。可以使用下面的方法实现:  
  17. ArrayList a=new ArrayList();  
  18. a.add(new Integer(1));  
  19. a.add(new Integer(2));  
  20. //……  
  21.   
  22. //当类集不能被修改时,可能引发 UnsupportedOperationException异常。企图将一个不兼容的对象加入到一个类集中时可能引发ClassCastException//异常。  

11.3 添加一组元素

 

[java] view plaincopy
  1. //: holding/AddingGroups.java  
  2. // Adding groups of elements to Collection objects.  
  3. import java.util.*;  
  4.   
  5. public class AddingGroups {  
  6.   public static void main(String[] args) {  
  7.     Collection<Integer> collection =  
  8.       new ArrayList<Integer>(Arrays.asList(12345));  
  9.     Integer[] moreInts = { 678910 };  
  10.     collection.addAll(Arrays.asList(moreInts));  
  11.     // Runs significantly faster, but you can‘t  
  12.     // construct a Collection this way:  
  13.     Collections.addAll(collection, 1112131415);  
  14.     Collections.addAll(collection, moreInts);  
  15.     // Produces a list "backed by" an array:  
  16.     List<Integer> list = Arrays.asList(1617181920);  
  17.     list.set(199); // OK -- modify an element  
  18.     // list.add(21); // Runtime error because the  
  19.                      // underlying array cannot be resized.  
  20.   }  
  21. ///:~  
    你也可以直接使用Arrays.asList()的输出,将其当作List,但是在这种情况下,其底层表示的是数组,因此不能调整尺寸。
    Arrays.asList()方法的限制是它对所产生的List的类型做出了最理想的假设,而并没有注意你会对它赋予什么样的类型。

[java] view plaincopy
  1. //: holding/AsListInference.java  
  2. // Arrays.asList() makes its best guess about type.  
  3. import java.util.*;  
  4.   
  5. class Snow {}  
  6. class Powder extends Snow {}  
  7. class Light extends Powder {}  
  8. class Heavy extends Powder {}  
  9. class Crusty extends Snow {}  
  10. class Slush extends Snow {}  
  11.   
  12. public class AsListInference {  
  13.   public static void main(String[] args) {  
  14.     List<Snow> snow1 = Arrays.asList(  
  15.       new Crusty(), new Slush(), new Powder());  
  16.   
  17.     // Won‘t compile:  
  18.     // List<Snow> snow2 = Arrays.asList(  
  19.     //   new Light(), new Heavy());  
  20.     // Compiler says:  
  21.     // found   : java.util.List<Powder>  
  22.     // required: java.util.List<Snow>  
  23.   
  24.     // Collections.addAll() doesn‘t get confused:  
  25.     List<Snow> snow3 = new ArrayList<Snow>();  
  26.     Collections.addAll(snow3, new Light(), new Heavy());  
  27.   
  28.     // Give a hint using an  
  29.     // explicit type argument specification:  
  30.     List<Snow> snow4 = Arrays.<Snow>asList(  
  31.        new Light(), new Heavy());  
  32.   }  
  33. ///:~  

11.4 容器的打印

[java] view plaincopy
  1. //: holding/PrintingContainers.java  
  2. // Containers print themselves automatically.  
  3. import java.util.*;  
  4. import static net.mindview.util.Print.*;  
  5.   
  6. public class PrintingContainers {  
  7.   static Collection fill(Collection<String> collection) {  
  8.     collection.add("rat");  
  9.     collection.add("cat");  
  10.     collection.add("dog");  
  11.     collection.add("dog");  
  12.     return collection;  
  13.   }  
  14.   static Map fill(Map<String,String> map) {  
  15.     map.put("rat""Fuzzy");  
  16.     map.put("cat""Rags");  
  17.     map.put("dog""Bosco");  
  18.     map.put("dog""Spot");  
  19.     return map;  
  20.   }   
  21.   public static void main(String[] args) {  
  22.     print(fill(new ArrayList<String>()));  
  23.     print(fill(new LinkedList<String>()));  
  24.     print(fill(new HashSet<String>()));  
  25.     print(fill(new TreeSet<String>()));  
  26.     print(fill(new LinkedHashSet<String>()));  
  27.     print(fill(new HashMap<String,String>()));  
  28.     print(fill(new TreeMap<String,String>()));  
  29.     print(fill(new LinkedHashMap<String,String>()));  
  30.   }  
  31. /* Output: 
  32. [rat, cat, dog, dog] 
  33. [rat, cat, dog, dog] 
  34. [dog, cat, rat] 
  35. [cat, dog, rat] 
  36. [rat, cat, dog] 
  37. {dog=Spot, cat=Rags, rat=Fuzzy} 
  38. {cat=Rags, dog=Spot, rat=Fuzzy} 
  39. {rat=Fuzzy, cat=Rags, dog=Spot} 
  40. *///:~  
    ArrayList和LinkedList都是List类型,从输出可以看出,它们都是按照被插入的顺序保存元素。两者不同之处不仅在于执行某些类型的操作时的性能,而且LinkedList包含的操作也多余ArrayList。

       HashSet,TreeSet和LinkedHashSet都是Set类型,输出显示在Set中,每个相同的项只保存一次,但是输出也显示了不同的Set实现存储元素的方式也不同。

       你不需要指定Map的尺寸,因为它会自动地调整尺寸。

       HashMap提供了最快的查找技术,也没有按照任何明显的顺序来保存其元素。TreeMap按照比较结果的升序保存键,而LinkedHashMap则按照插入顺序保存键,同时还保留了HashMap的查询速度。

11.5 List

List接口(从Collection继承而来,使用基于0的下标)

[java] view plaincopy
  1. void add(int index,Object obj) 插入点以后的元素将后移  
  2. boolean addAll(int index,Collection c) 如果调用列表改变了,返回true,否则返回false  
  3. Object get(int index)  
  4. int indexOf(Object obj) 返回obj对象在列表中的索引,不存在返回-1  
  5. int lastIndexOf(Object obj) 返回obj在列表中的最后一个实例的下标,不存在返回-1  
  6. ListIterator listIterator()  
  7. ListIterator listIterator(int index) 返回index开始的迭代程序  
  8. Object set(int index,Object obj) 对列表index处的值进行修改  
  9. List subList(int start,int end) 从start到end-1  

11.6 迭代器

iterator实现Iterator接口或者ListIterator接口。
Iterator接口

[java] view plaincopy
  1. boolean hasNext()  
  2. Object next() 如果没有下一个元素则引发NoSuchElementException异常。  
  3. void remove() 删除当前元素,如果试图在调用next()方法后调用remove()方法则引发IllegalStateException异常。  
  4.  ListIterator接口  
  5. void add(Object obj) 将一个元素插入到当前元素之前,调用next()方法将返回该元素。  
  6. boolean hasNext()  
  7. boolean hasPrevious()  
  8. Object next() 如果不存在引发NoSuchElementException  
  9. int nextIndex() 如果不存在返回列表的大小  
  10. void remove()  
  11. void set(Object obj) 修改当前元素  
  12.   
  13. public void test1() {  
  14.         ArrayList al = new ArrayList();  
  15.         for (int i = 1; i < 10; i ) {  
  16.             al.add("ArrayList Element:" i);  
  17.         }  
  18.         Iterator itr = al.listIterator();  
  19.         while (itr.hasNext()) {  
  20.             Object obj = itr.next();  
  21.             System.out.println(obj);  
  22.         }  
  23.     }  
  24.   
  25. public void test2() {  
  26.         HashSet hs = new HashSet();  
  27.         System.out.println("HashSet");  
  28.         for (int i = 1; i < 10; i ) {  
  29.             hs.add("HashSet Element:" i);  
  30.         }  
  31.         Iterator itr = hs.iterator();  
  32.         while (itr.hasNext()) {  
  33.             Object obj = itr.next();  
  34.             System.out.println(obj);  
  35.         }  
  36.     }  
  37.   
  38.     public void test3() {  
  39.         TreeSet ts = new TreeSet();  
  40.         System.out.println("TreeSet");  
  41.         for (int i = 1; i < 10; i ) {  
  42.             ts.add("TreeSet Element:" i);  
  43.         }  
  44.         Iterator itr = ts.iterator();  
  45.         while (itr.hasNext()) {  
  46.             Object obj = itr.next();  
  47.             System.out.println(obj);  
  48.         }  
  49.     }  
  50.   
  51.     public void test4()  
  52.     {  
  53.         HashMap hm=new HashMap();  
  54.         for ( int i=0;i<10;i )  
  55.         {  
  56.             hm.put("item" i,"value" i);  
  57.         }  
  58.   
  59.         Set set=hm.entrySet();  
  60.         Iterator itr=set.iterator();  
  61.         while (itr.hasNext())  
  62.         {  
  63.             Map.Entry me=(Map.Entry)itr.next();  

11.7 LinkedList

         LinkedList还添加了可以使其用作栈、队列或双端队列的方法。

11.8 Stack

[java] view plaincopy
  1. //: net/mindview/util/Stack.java  
  2. // Making a stack from a LinkedList.  
  3. package net.mindview.util;  
  4. import java.util.LinkedList;  
  5.   
  6. public class Stack<T> {  
  7.   private LinkedList<T> storage = new LinkedList<T>();  
  8.   public void push(T v) { storage.addFirst(v); }  
  9.   public T peek() { return storage.getFirst(); }  
  10.   public T pop() { return storage.removeFirst(); }  
  11.   public boolean empty() { return storage.isEmpty(); }  
  12.   public String toString() { return storage.toString(); }  
  13. ///:~  

11.9 Set

Set接口(从Collection派生,没有定义新的方法)

Set不允许有重复的元素,用Iterator()方法来区分重复与否。
对Set调用add(Object obj)方法,如果obj已经存在集合中,将返回false。

11.9.1 SortedSet接口

[java] view plaincopy
  1. Comparator comparator() 返回调用排序集合的比较函数,如果改集合使用自然顺序,则返回null  
  2. Object first() 返回被排序集合的第一个元素  
  3. SortedSet headSet(Object end) 返回一个包含小于end元素的SortedSet  
  4. Object last() 返回调用排序集合的最后一个元素  
  5. SortedSet subSet(Object start,Object end) 包括从start到end-1  
  6. SortedSet tailSet(Object start) 返回包含大于等于start的元素  
  7.  ArrayList扩展AstractList类,并执行List接口。ArrayList支持动态长度的数组。  
  8. LinkList扩展了AbstractSequentialList,执行List接口。提供连接列表。  
  9. HashSet扩展AbstractSet实现Set接口,元素没有顺序。对于大集合提供常量级基本操作。  
  10. TreeSet使用树来存储的Set,对象按升序存储。访问和检索非常快。  

11.10 Map

[java] view plaincopy
  1. (1) 添加、删除操作:  
  2.   Object put(Object key, Object value): 将互相关联的一个关键字与一个值放入该映像。如果该关键字已经存在,那么与此关键字相关的新值将取代旧值。方法返回关键字的旧值,如果关键字原先并不存在,则返回null  
  3.   Object remove(Object key): 从映像中删除与key相关的映射  
  4.   void putAll(Map t): 将来自特定映像的所有元素添加给该映像  
  5.   void clear(): 从映像中删除所有映射  
  6.   “键和值都可以为null。但是,您不能把Map作为一个键或值添加给自身。”  
  7.   (2) 查询操作:  
  8.   Object get(Object key): 获得与关键字key相关的值,并且返回与关键字key相关的对象,如果没有在该映像中找到该关键字,则返回null  
  9.   boolean containsKey(Object key): 判断映像中是否存在关键字key  
  10.   boolean containsValue(Object value): 判断映像中是否存在值value  
  11.   int size(): 返回当前映像中映射的数量  
  12.   boolean isEmpty() :判断映像中是否有任何映射  
  13.   (3) 视图操作 :处理映像中键/值对组  
  14.   Set keySet(): 返回映像中所有关键字的视图集  
  15.   “因为映射中键的集合必须是唯一的,您用Set支持。你还可以从视图中删除元素,同时,关键字和它相关的值将从源映像中被删除,但是你不能添加任何元素。”  
  16.   Collection values():返回映像中所有值的视图集  
  17.   “因为映射中值的集合不是唯一的,您用Collection支持。你还可以从视图中删除元素,同时,值和它的关键字将从源映像中被删除,但是你不能添加任何元素。”  
  18.   Set entrySet(): 返回Map.Entry对象的视图集,即映像中的关键字/值对  
  19.   “因为映射是唯一的,您用Set支持。你还可以从视图中删除元素,同时,这些元素将从源映像中被删除,但是你不能添加任何元素。”  
11.11 Queue

11.12 Collection和Iterator

11.13 Foreach与迭代器

        之所以能够工作,是因为java SE5引入了新的被称为Iterable的接口,该接口包含一个能够产生Iterator的iterator()方法,并且Iterable接口被foreach用来在序列中移动。因此如果你创建了任何实现Iterable的类,都可以将它用于foreach语句中:

[java] view plaincopy
  1. //: holding/IterableClass.java  
  2. // Anything Iterable works with foreach.  
  3. import java.util.*;  
  4.   
  5. public class IterableClass implements Iterable<String> {  
  6.   protected String[] words = ("And that is how " +  
  7.     "we know the Earth to be banana-shaped.").split(" ");  
  8.   public Iterator<String> iterator() {  
  9.     return new Iterator<String>() {  
  10.       private int index = 0;  
  11.       public boolean hasNext() {  
  12.         return index < words.length;  
  13.       }  
  14.       public String next() { return words[index++]; }  
  15.       public void remove() { // Not implemented  
  16.         throw new UnsupportedOperationException();  
  17.       }  
  18.     };  
  19.   }   
  20.   public static void main(String[] args) {  
  21.     for(String s : new IterableClass())  
  22.       System.out.print(s + " ");  
  23.   }  
  24. /* Output: 
  25. And that is how we know the Earth to be banana-shaped. 
  26. *///:~  

11.4 总结

简单容器分类:


Java&&持有对象(容器小结)