1. Java集合类库中最重要的两个接口Collection和Map,其中Collection接口又再次划分为 List和Set两大子接口,List中可以包含重复的元素,Set中则不可以。以下列举出一些常用的集合实现类,他们均分别继承自这两个接口:
1) ArrayList: 一种可以动态增长和缩减的索引序列(动态数组,类似于C++中的vector);
2) LinkedList: 一种可以在任何位置进行高效的插入和删除操作的有序序列(类似于C++中list);
3) ArrayDeque: 一种用循环数组实现的双端队列(类似于C++中的deque);
4) HastSet:一种没有重复元素的无序集合(C++的标准库中并未提供hashset集合,但是Windows的VC和Linux平台下的gcc均各自提供了hashset容器);
5) TreeSet: 一种有序集(类似于C++中的set);
6) EnumSet: 一种包含枚举类型值的集;
7) LinkedHashSet: 一种可以记住元素插入次序的集,在其内部由LinkedList负责维护插入的次序,HashSet来维护Hash;
8) HashMap:一种存储键值对关联的数据结构(C++的标准库中并未提供hashmap集合,但是Windows的VC和Linux平台下的gcc均各自提供了hashmap容器);
9) TreeMap:一种键值有序排列的映射表(类似于C++中的map);
10) EnumMap:一种键值属于枚举类型的映射表;
11) LinkedHashMap:一种可以记住键值项插入次序的映射表;
2. ArrayList:该集合的底层是通过动态数组来实现的,集合构造的时候可以指定一个初始容量,当插入的元素过多导致已有的容量不能容纳新元素是,其底层数组的容量将自动增长原有容量的1.5 倍,这样会带来一定的空间浪费,但是为了避免经常扩张而带来的性能开销,只能是用空间换取时间了。如果在容器的中间添加或者删除一个元素都将会导致后面的元素向后或向前移动一个位置,如果元素数量较多且该操作比较频繁,将会导致系统的性能降低,然而对于容器中元素的随机访问性能较好,以下为 ArrayList的常用示例代码:
1 publicstaticvoidshowIterator() {2 ArrayListlist=newArrayList();3 list.add("Monday");4 list.add("Tuesdag");5 list.add("Wednesday");6 Iteratoriterator=null;7 iterator=list.iterator();8 //while9 while(iterator.hasNext()) {10 String element=iterator.next();11 System.out.println(element);12 }13 //for14 for(iterator=list.iterator(); iterator.hasNext();) {15 String element=iterator.next();16 System.out.println(element);17 }18 //for each19 for(String element : list) {20 System.out.println(element);21 }22 }23 24 publicstaticvoidshowSetAndGet() {25 ArrayListnums=newArrayList();26 nums.clear();27 nums.add("One");28 nums.add("Two");29 nums.add("Three");30 System.out.println(nums);31 nums.set(0,"Uno");32 nums.set(1,"Dos");33 nums.set(2,"Tres");34 for(inti=0; ial=newArrayList();40 System.out.println("Initial size of al:"+al.size());41 al.add("C");42 al.add("A");43 al.add("E");44 al.add("B");45 al.add(1,"A2");46 System.out.println("Size of al after additions:"+al.size());47 System.out.println("Contents of al:"+al);48 al.remove("F");49 al.remove(2);50 System.out.println("Size of al after deletions:"+al.size());51 System.out.println("Contents of al:"+al);52 Iteratorit=al.iterator();53 //Notes:remove() must be called after next()54 it.next();55 it.remove();56 System.out.println("Size of al after deletions:"+al.size());57 System.out.println("Contents of al:"+al);58 }59 60 publicstaticvoidshowSubListAndCopyToArray() {61 ArrayListarrayList=newArrayList();62 arrayList.add("1");63 arrayList.add("2");64 arrayList.add("3");65 arrayList.add("4");66 arrayList.add("5");67 Listlst=arrayList.subList(1,3);68 for(inti=0; iaList=newArrayList();87 aList.add("1");88 aList.add("2");89 aList.add("3");90 aList.add("4");91 aList.add("5");92 93 ListIteratorlistIterator=aList.listIterator();94 while(listIterator.hasNext()) {95 System.out.println(listIterator.next());96 System.out.println("Previous:"+listIterator.previousIndex());97 System.out.println("Next:"+listIterator.nextIndex());98 }99 while(listIterator.hasPrevious()) {100 System.out.println(listIterator.previous());101 System.out.println("Previous:"+listIterator.previousIndex());102 System.out.println("Next:"+listIterator.nextIndex());103 }104 listIterator=aList.listIterator(2);105 listIterator.next();106 listIterator.set("100");107 listIterator.next();108 listIterator.remove();109 for(String str : aList)110 System.out.println(str);111 112 if(aList.contains("4"))113 System.out.println("True");114 else115 System.out.println("False");116 }117 118 publicstaticvoidshowFillAndReplace() {119 ArrayListarrayList=newArrayList();120 arrayList.add("A");121 arrayList.add("B");122 arrayList.add("A");123 arrayList.add("C");124 arrayList.add("D");125 Collections.replaceAll(arrayList,"A","Replace All");126 System.out.println(arrayList);127 Collections.fill(arrayList,"REPLACED");128 System.out.println(arrayList);129 }130 131 publicstaticvoidshowCollectionOperation() {132 Listcolours=newArrayList();133 colours.add("red");134 colours.add("green");135 colours.add("blue");136 137 System.out.println(colours);138 Collections.swap(colours,0,2);139 System.out.println(colours);140 141 Collections.reverse(colours);142 System.out.println(colours);143 144 Collections.sort(colours);145 System.out.println(Arrays.toString(colours.toArray()));146 Collections.sort(colours, Collections.reverseOrder());147 System.out.println(Arrays.toString(colours.toArray()));148 149 intindex=Collections.binarySearch(colours,"green");150 System.out.println("Element found at :"+index);151 ArrayListarrayList=newArrayList();152 arrayList.add(newInteger("3"));153 arrayList.add(newInteger("1"));154 arrayList.add(newInteger("8"));155 arrayList.add(newInteger("3"));156 arrayList.add(newInteger("5"));157 System.out.println(Collections.min(arrayList));158 System.out.println(Collections.max(arrayList));159 }160 161 publicstaticvoidshowMinMax() {162 ArrayListarrayList=newArrayList();163 arrayList.add(newInteger("3"));164 arrayList.add(newInteger("1"));165 arrayList.add(newInteger("8"));166 arrayList.add(newInteger("3"));167 arrayList.add(newInteger("5"));168 System.out.println(Collections.min(arrayList));169 System.out.println(Collections.max(arrayList));170 }171 172 publicstaticvoidshowSynchronizedList() {173 ArrayList arrayList=newArrayList();174 List list=Collections.synchronizedList(arrayList);175 //list之后的并发操作将不再需要synchronized关键字来进行同步了。176 }
3. LinkedList: 该集合是通过双向链表来实现的,对于指定位置元素的遍历其内部做了一个小的优化,如果position大于len/2,由于内部的数据结构是双向链表,因此可以从后向前遍历,以减少遍历过程中节点跳转的次数。ArrayList中的大部分代码示例都适用于LinkedList,以下近给出 LinkedList特有的常用示例代码:
1 publicstaticvoidshowNewFeatures(String[] args) {2 LinkedListlList=newLinkedList();3 lList.add("1");4 lList.add("2");5 lList.add("3");6 lList.add("4");7 lList.add("5");8 9 System.out.println("First element of LinkedList is :"+lList.getFirst());10 System.out.println("Last element of LinkedList is :"+lList.getLast());11 System.out.println(lList);12 13 String str=lList.removeFirst();14 System.out.println(str+"has been removed");15 System.out.println(lList);16 str=lList.removeLast();17 System.out.println(str+"has been removed");18 System.out.println(lList);19 20 lList.addFirst("1");21 System.out.println(lList);22 lList.addLast("5");23 System.out.println(lList);24 }
4. ArrayList和LinkedList的相同点:
1) 都是接口List的实现类;
2) 都可以通过iterator()方法返回Iterator迭代器对象,并可以通过该对象遍历容器中的元素;
3) 如果多个Iterator实例同时引用同一个集合对象,那么当有一个正在遍历,而另外一个修改(add/remove)了集合对象中的元素,对于第一个迭代器再进行迭代时将会引发ConcurrentModificationException异常的发生。
5. ArrayList和LinkedList的不同点:
1) 对ArrayList和LinkedList而言,在列表末尾增加一个元素所花的开销都是固定的。对ArrayList而言,主要是在内部数组中增加一项,指向所添加的元素,偶尔可能会导致对数组重新进行分配;而对LinkedList而言,这个开销是统一的,分配一个内部Entry对象。
2) 在ArrayList的中间插入或删除一个元素意味着这个列表中剩余的元素都会被移动;而在LinkedList的中间插入或删除一个元素的开销是固定的。
3) LinkedList不支持高效的随机元素访问。
4) ArrayList的空间浪费主要体现在在list列表的结尾预留一定的容量空间,而LinkedList的空间花费则体现在它的每一个元素都需要消耗相当的空间 在C++的标准库中,ArrayList和LinkedList之间的使用差异以及各自的优缺点也同样反映于vector和list。
6. HashSet: 散列表为每个对象计算出一个整数(通过Object缺省的或类重载的hashCode域方法),称为散列码。在Java中,散列表是使用链表的数组来实现的,每个链表被称为一个哈希桶。如果想在哈希表中查找一个对象,则需要先计算对象的hashCode,之后对表内的桶数取余数,得到的结果就是哈希桶的索引,此时如果该桶为空桶,就可以直接将该对象插入到该桶中,如果已经有对象存在了,则需要逐个进行比较,一旦发现该与该对象相等的对象(equals() 返回true),就会放弃本次插入操作,否则将该对象插入到该桶的末端。HashSet在构造的时候提供两个参数,一个是initialCapacity 指定了桶的数量(实际的桶数为2的initialCapacity次幂),另一个是loadFactortian(0.0--1.0,推荐值为 0.75),当桶的填充百分比达到该值后,哈希表内的哈希桶数将double,重新填充已有对象,该操作被称为rehash,rehash是十分影响效率的操作,因为为了尽可能避免该事件的发生,因可能在构造HashSet的时候给出一个合理的参数。以下为HashSet的常用示例代码:
1 publicstaticvoidshowAddAndIterator() {2 HashSeths=newHashSet();3 hs.add("B");4 hs.add("A");5 hs.add("D");6 hs.add("E");7 hs.add("C");8 hs.add("F");9 System.out.println(hs);10 Iteratorit=hs.iterator();11 while(it.hasNext())12 System.out.println(it.next());13 }14 publicstaticvoidshowRemoveAndClearAndContains() {15 HashSethSet=newHashSet();16 hSet.add(newInteger("1"));17 hSet.add(newInteger("2"));18 hSet.add(newInteger("3"));19 System.out.println(hSet.contains(newInteger("3")));20 System.out.println(hSet);21 booleanblnRemoved=hSet.remove(newInteger("2"));22 System.out.println(hSet.contains(newInteger("2")));23 System.out.println(blnRemoved);24 System.out.println(hSet);25 hSet.clear();26 System.out.println(hSet);27 System.out.println(hSet.isEmpty());28 }29 30 publicstaticvoidshowToArrayListAndArray() {31 HashSeths=newHashSet();32 hs.add("B");33 hs.add("A");34 hs.add("D");35 System.out.println(hs);36 Listlist=newArrayList(hs);37 Object[] objects=list.toArray();38 for(Object obj : objects)39 System.out.println("Object ="+obj);40 String[] strs=list.toArray(newString[0]);41 for(String str : strs)42 System.out.println("String ="+str);43 }44 45 publicstaticvoidshowToHashSetAndRemoveDuplicate() {46 Integer[] numbers={7,7,8,9,10,8,8,9,6,5,4};47 Listlist=Arrays.asList(numbers);48 Setset=newHashSet(list);49 for(Integer o : set)50 System.out.print(o+",");51 }52 53 publicstaticvoidshowMinMax() {54 HashSethashSet=newHashSet();55 hashSet.add(newLong("9"));56 hashSet.add(newLong("4"));57 hashSet.add(newLong("2"));58 hashSet.add(newLong("2"));59 hashSet.add(newLong("3"));60 Object objMin=Collections.min(hashSet);61 System.out.println("Minimum Element of Java HashSet is :"+objMin);62 Object objMax=Collections.max(hashSet);63 System.out.println("Maximum Element of Java HashSet is :"+objMax);64 }65 66 publicstaticvoidshowSynchronizedSet() {67 HashSet hashSet=newHashSet();68 Set set=Collections.synchronizedSet(hashSet);69 //set之后的并发操作将不再需要synchronized关键字来进行同步了。70 }
7. TreeSet:该集合为有序集合,数据在插入集合后便按照自定义的排序规则将插入的对象进行排序,该集合主要是通过两种方式排序插入对象的,一种是要求集合元素类必须是Comparable的实现类,这样在插入对象的时候,集合可以根据compareTo方法的返回值来确定新插入对象的位置,另外一种方式是通过在构造该集合对象的时候,传入Comparator的实现类作为参数,之后所有插入的对象都是通过 Comparator的compare方法的返回值来决定新对象的位置。该集合是通过RBTree(红黑树)来实现排序的,这一点和 C++标准库中的set和map是一致的。由于对象插入集合之后是有序的,因此该集合的插入效率要低于HashSet的插入效率。TreeSet和 HashSet相比主要的差异来自于对象的排序规则,以上HashSet的示例代码均适用于TreeSet,下面只是列出对象比较的代码:
1 publicclassItemimplementsComparable{2 publicintcompareTo(Item other) {3 returnpartNumber-other.partNumber;4 }5 }6 publicstaticvoidmain(String[] args) {7 SortedSetparts=newTreeSet();8 parts.add(newItem("Toaster",1234));9 parts.add(newItem("Widget",4562));10 parts.add(newItem("Modem",9912));11 System.out.println(parts);12 13 SortedSetsortByDescription=newTreeSet(newComparator() {14 publicintcompare(Item a,Item b) {15 String descA=a.getDescription();16 String descB=b.getDescription();17 returndescA.compareTo(descB);18 }19 });20 sortByDescription.addAll(parts);21 System.out.println(sortByDescription);22 }
8. PriorityQueue(优先级对象): 该容器也是有序集合,和TreeSet不同的是,该集合只是保证当从集合的头部取出数据的时候,总是取出队列中最小(优先级最高)的元素。该集合内部是通过"堆"的数据结构实现的,该结构只有第一个元素(头部元素)保证为该集合中最大的或最小的元素,其余元素没有固定的顺序,但是当集合有新的对象从尾部插入或是从头部取出时,集合内部的相关元素会进行比较的比较最终再次决定出谁是最大或最小的元素作为头部元素。在JDK提供的classes中Timer是通过该数据结构实现的,从而保证了Timer每次获取任务时都是最应该被调度的TimerTask,见如下代码:
1 publicclassTestMain {2 publicstaticvoidmain(String[] args) {3 PriorityQueuepq=newPriorityQueue();4 pq.add("1");5 pq.add("6");6 pq.add("4");7 pq.offer("5");8 pq.offer("3");9 pq.offer("2");10 pq.offer("7");11 //以下输出将以无序的结果输出12 System.out.println(pq);13 //以下输出将以有序的结果输出14 while(pq.peek()!=null) {15 String str=pq.poll();16 System.out.println(str);17 }18 intinitCapacity=20;19 PriorityQueuepq1=newPriorityQueue(initCapacity,20 newComparator() {21 publicintcompare(TestComparator t1, TestComparator t2) {22 returnt1.getID()-t2.getID();23 }24 });25 pq1.offer(newTestComparator(1));26 pq1.offer(newTestComparator(6));27 pq1.offer(newTestComparator(4));28 pq1.offer(newTestComparator(5));29 pq1.offer(newTestComparator(3));30 pq1.offer(newTestComparator(2));31 pq1.offer(newTestComparator(7));32 System.out.println("The following is for TestComparator.");33 System.out.println(pq1);34 while(pq1.peek()!=null) {35 intid=pq1.poll().getID();36 System.out.println(id);37 }38 }39 }40 41 classTestComparator {42 publicTestComparator(intid) {43 _id=id;44 }45 publicintgetID() {46 return_id;47 }48 publicString toString() {49 returnInteger.toString(_id);50 }51 privateint_id;52 }
9. HashMap:其内部数据结构的逻辑类似于HashSet,只是Map存储的都是key/value的键值映射关系,key相当于HashSet中的对象,value只是附着于key的对象,使用者一般都是通过key的值去HashMap中搜索,找到并返回该key以及相关联的value,其内部实现机制可参考HashSet。在接口方面主要的不同点是Map对象可以生成3个集合的视图(仅仅是视图,没有对象copy,视图的底层容器仍然来自于原映射对象集合,如果在其中任意视图或原集合删除和添加数据都会及时反应与其他视图和映射集合)。该规则同样适用于TreeMap。见以下常用代码示例:
1 publicstaticvoidshowGetAndPut() {2 HashMaphm=newHashMap();3 hm.put("A",newDouble(3.34));4 hm.put("B",newDouble(1.22));5 hm.put("C",newDouble(1.00));6 hm.put("D",newDouble(9.22));7 hm.put("E",newDouble(-19.08));8 //随机的获取HashMap中的数据9 Set>set=hm.entrySet();10 for(Map.Entryme : set) {11 System.out.print(me.getKey()+":");12 System.out.println(me.getValue());13 }14 doublebalance=hm.get("A");15 //输出1003.3416 hm.put("A", balance+1000);17 System.out.println(hm.get("A"));18 }19 20 publicstaticvoidshowContainsAndRemove() {21 HashMaphashMap=newHashMap();22 hashMap.put("1","One");23 hashMap.put("2","Two");24 hashMap.put("3","Three");25 System.out.println(hashMap.containsValue("Three"));26 String str=hashMap.remove("2");27 System.out.println("old value of 2 ="+str);28 System.out.println(hashMap.containsValue("Two"));29 Setst=hashMap.keySet();30 st.remove("1");31 System.out.println("The size is equal to"+hashMap.size());32 System.out.println(hashMap.containsKey("3"));33 }34 /*结果如下35 true36 old value of 2 = Two37 false38 The size is equal to 139 true*/40 41 publicstaticvoidshowIterator() {42 String names[]={"Mercury","Venus","Earth","Mars","Jupiter"43 ,"Saturn","Uranus","Neptune","Pluto"};44 floatdiameters[]={ 4800f,12103.6f,12756.3f, 6794f, 142984f45 , 120536f, 51118f, 49532f, 2274f };46 Mapmap=newHashMap();47 for(inti=0, n=names.length; iit=map.keySet().iterator();50 while(it.hasNext()) {51 String str=it.next();52 System.out.println(str+":"+map.get(str));53 }54 }55 56 publicstaticvoidshowSynchronizedMap() {57 TreeMaptreeMap=newTreeMap();58 Mapmap=Collections.synchronizedMap(treeMap);59 //Map之后的并发操作将不再需要synchronized关键字来进行同步了。60 }
10. TreeMap:TreeMap和TreeSet之间的相似性和主要差异就像HashMap之于HashSet,见以下常用代码示例:
1 publicstaticvoidshowSubMapAndHeadMapAndTailMap() {2 TreeMapsortedMap=newTreeMap();3 sortedMap.put("Adobe","Mountain View, CA");4 sortedMap.put("IBM","White Plains, NY");5 sortedMap.put("Learning Tree","Los Angeles, CA");6 sortedMap.put("Microsoft","Redmond, WA");7 sortedMap.put("Netscape","Mountain View, CA");8 sortedMap.put("O'Reilly","Sebastopol, CA");9 sortedMap.put("Sun","Mountain View, CA");10 System.out.println(sortedMap);11 //firstKey and lastKey 是SortedMap中提供的方法,HashMap中没有。12 String low=sortedMap.firstKey(), high=sortedMap.lastKey();13 System.out.println(low);14 System.out.println(high);15 Iteratorit=sortedMap.keySet().iterator();16 inti=0;17 while(it.hasNext()) {18 if(i==3)19 low=it.next();20 if(i==6)21 high=it.next();22 else23 it.next();24 i++;25 }26 System.out.println(low);27 System.out.println(high);28 //以下3个方法也是SortedMap中提供的方法,HashMap中没有。29 System.out.println(sortedMap.subMap(low, high));30 System.out.println(sortedMap.headMap(high));31 System.out.println(sortedMap.tailMap(low));32 }
11. LinkedHashSet和LinkedHashMap:这两个集合与HashSet和HashMap唯一的差异是LinkedHashSet和LinkedHashMap通过内部实现的双向链表保留了集合元素的插入顺序,见如下代码:
1 publicstaticvoidmain(String[] a) {2 Mapmap=newLinkedHashMap();3 map.put("1","value1");4 map.put("2","value2");5 map.put("3","value3");6 map.put("2","value4");7 for(Iteratorit=map.keySet().iterator(); it.hasNext();) {8 String key=it.next();9 String value=map.get(key);10 System.out.println(value);11 }12 }13 /*结果如下:14 value115 value416 value3*/17 18 //基于Values的排序后输出Keys19 publicstaticvoidmain(String[] a) {20 MapyourMap=newHashMap();21 yourMap.put("1","one");22 yourMap.put("2","two");23 yourMap.put("3","three");24 25 Mapmap=newLinkedHashMap();26 ListkeyList=newArrayList(yourMap.keySet());27 ListvalueList=newArrayList(yourMap.values());28 SetsortedSet=newTreeSet(valueList);29 String[] sortedArray=sortedSet.toArray(newString[0]);30 intsize=sortedArray.length;31 32 for(inti=0; iref=map.keySet();36 Iteratorit=ref.iterator();37 while(it.hasNext()) {38 String i=(String) it.next();39 System.out.println(i);40 }41 }
12. EnumSet和EnumMap,这两个集合可以看做是类型参数特化后的Set>和Map,V>,EnumSet没有显示的构造函数,而是通过一组工厂方法来创建了,见如下代码:
1 enumWeekdays {2 Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday3 }4 publicstaticvoidmain(String[] a) {5 EnumSetes1=EnumSet.allOf(Weekdays.class);6 EnumSetes2=EnumSet.noneOf(Weekdays.class);7 EnumSetes3=EnumSet.range(Weekdays.Thursday, Weekdays.Sunday);8 EnumSetes4=EnumSet.of(Weekdays.Monday,Weekdays.Saturday);9 System.out.println("es1 ="+es1);10 System.out.println("es2 ="+es2);11 System.out.println("es3 ="+es3);12 System.out.println("es4 ="+es4);13 }14 /*结果如下:15 es1 = [Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday]16 es2 = []17 es3 = [Thursday, Friday, Saturday, Sunday]18 es4 = [Monday, Saturday]*/
13. 集合视图:顾名思义,所有的集合视图和数据库中的普通视图一样,并不存储真实是的容器元素,而只是建立一套针对原有底层集合数据的引用机制,针对所有视图的操作或底层集合的操作都会同时相互影响,如插入和删除等,但是对于视图而言,插入操作如果作用于其范围之外将会引发异常。对于不同类别的视图其操作也存在不同的限制。 1). subList:获取底层集合中某一范围的元素,如List group2 = staff.asList(10,20); 这第一个索引上的数据是被包含的,第二个索引的数据是不被包含的。如果执行了group2.clear()操作情况了视图中的数据,那么staff中这段范围内的数据也会被连同删除。对于有序集合和映射表(Map),可以使用排序顺序而不是元素位置建立子范围,如SortedSet接口声明的 SortedSet subSet(E from,E to); SortedSet headSet(E to); SortedSet tailSet(E from); 注意这3个参数的类型均不是元素的索引,而是对象本身。SortedMap中也有类似的方法,如SortedMap subMap(K from,K to); SortedMap headMap(K to); SortedMap tailMap(K from)。在NavigableSet中提供更为丰富的接口,如NavigableSet subSet(E from,boolean fromInclusive,E to,boolean toInclusive); NavigableSet headSet(E to,boolean toInclusive); NavigableSet tailSet(E from,boolean fromInclusive); 2). 不可修改的视图: Collections.unModifiableCollection(); Collections.unModifiableList(); //用于ArrayList、LinkedList Collections.unModifiableSet(); //用于HashSet、TreeSet、LinkedHashSet Collections.unModifiableSortedSet();//用于TreeSet Collections.unModifiableMap(); //用于HashMap、TreeMap、LinkedHashMap Collections.unModifiableSortedMap();//用于TreeMap 如List staff = new LinkedList(); List unmodifiableList = new Collections.unmodifiableList(staff); 这里unmodifiableList作为一个List对象,所有访问器的方法均可像普通List一样操作,但是对于更改器方法的调用将会引发 UnsupportedOperationException异常。如果确实需要修改数据只能通过原始集合来完成。 3) 同步视图: Collections.synchronizedList(); //用于ArrayList、LinkedList Collections.synchronizedSet(); //用于HashSet、TreeSet、LinkedHashSet Collections.synchronizedSortedMap();//用于TreeMap Collections.synchronizedSortedSet();//用于TreeSet Collections.synchronizedMap(); //用于HashMap、TreeMap、LinkedHashMap 之后所有通过同步视图访问底层集合的操作都将是线程安全的,即synchronized关键字就不需要在集合的外部添加了,但是对于底层集合的直接访问仍然是线程不安全。 4) 被检查视图:见以下两种情况,第一种情况将会在集合执行(String)rawList.get()操作时抛出ClassCastException异常,第一种情况则会在rawList.add()操作时就立即抛出ClassCastException。
1 publicvoiduncheckedListTest() {2 ArrayListstrings=newArrayList();3 ArrayList rawList=strings;4 rawList.add(newDate());//no exception is raised here.5 String ss=(String)rawList.get(0);//exception will be thrown here.6 }7 8 publicvoidcheckedListTest() {9 ArrayListstrings=newArrayList();10 ArrayListsafeStrings=Collections.checkedList(strings,String.class);11 ArrayList rawList=safeStrings;12 rawList.add(newDate());//exception will be thrown here.13 }
注:从集合框架的整体设计技巧、扩展性、效率等方面综合比较,Java在此方面和C++的stl相比还是存在一定的差距。特别是扩展性和效率方面,C++ 的标准库定义了更多更灵活的模参扩展。由于标准库都是通过模板的方式实现的,因此其执行效率要明显优于基于虚函数的虚指针和虚表的这种动态绑定的多态方式,其不足只是编译速度稍微慢罢了。 14. 算法: 在C++中提供了一套泛型算法,主要涵盖排序、搜索和比较等通用操作,由于这些泛型算法完全基于各种集合提供的迭代器(iterator)统一接口,因此可以达到一种高度的泛型操作,以及算法函数和集合之间的完全松耦合。见如下C++代码:
1 #include2 #include3 #include4 usingnamespacestd;5 intmain()6 {7 vectorv1;8 for(inti=0; i<10;++i)9 v1.push_back(i);10 sets1;11 for(inti=0; i<20;++i)12 s1.insert(i);13 sort(v1.begin(),v1.end());14 binary_search(v1.begin(),v1.end(),5);15 binary_search(s1.begin(),s1.end(),5);16 return0;17 }
在Java中同样提供了这样的泛型算法,不同的是这些算法函数都是Collections中静态方法。见如下Java代码:
1 publicstaticvoidmain(String[] args) {2 Listv1=newArrayList();3 for(inti=0; i<10;++i)4 v1.add(i);5 6 Listl1=newLinkedList();7 for(inti=0; i<20;++i)8 l1.add(i);9 10 Collections.sort(v1);11 Collections.sort(l1);12 Collections.binarySearch(v1,5);13 Collections.binarySearch(l1,5);14 }