JAVA学习笔记--初识容器类库
一、前言
JAVA中一切皆為對象,因而,持有對象顯得尤為重要。
在JAVA中,我們可以通過創建一個對象的引用的方式來持有對象:
HoldingObject holding;
也可以創建一個對象數組來持有一組特定類型的對象:
HoldingObject holding ?= new HoldingObject[10];
但是,一個對象引用只能持有一個對象,一個對象數組只能持有固定數量且為某一特定類型的對象;然而,我們常常會遇到這種情況,在編寫程序時,我們并不知道要創建多少個對象,甚至不知道要創建的對象的類型,因此,我們需要能夠在任意時刻任意位置創建任意數量的對象,這是上面兩種方法所做不到的。JAVA實用類庫提供了一套相當完整的容器類來解決這個問題,其中的基本類型是List,Set,Queue,Map,我們稱之為“容器”。
?
二、容器的分類
?
如上圖所示,是一個簡單的容器分類。可以看到,其實只有兩種容器Collection和Map,而Collection又可以分為List,Set和Queue。它們各有兩到三個實現,如:ArrayList,LinkedList是List的實現;HashMap,TreeMap是Map的實現。在上圖中,常用的容器用黑色粗線框表示;點線框表示接口;實線框表示具體的類;空心箭頭的點線表示一個特定的類實現了一個接口;實心箭頭表示某個類可以生成箭頭所指向類的對象。
1)Collection:
Collection保存一個獨立的元素序列, 這些元素序列都服從一條或多條規則。Collection是一個接口,它表示一組對象,這些對象也被稱為collection的元素,一些collection允許有重復元素,另一些則不允許。JDK不提供此接口的任何直接實現,它提供更具體的子接口實現(List,Set,Queue),此接口常用來傳遞collection,并在需要最大普遍性的地方操作這些collection。下面簡單列出Collection的一些方法(截圖自J2SE6_API):
?
a)List:必須按照插入的順序保存元素
List是有序的collection,此接口的用戶可以對列表中的每個元素的插入位置進行精確控制,用戶可以根據元素的整數索引(在列表中的位置)來訪問元素,并搜索列表中的元素。List接口在Collection的基礎上添加了大量的方法,使得可以在List的中間插入和移除元素。List允許在它被創建之后添加元素、移除元素,或者自我調整尺寸,這正是它的價值所在:一種可修改的序列。有兩種類型的List實現:
ArrayList:隨機訪問元素時比較快,但是插入和移除元素時比較慢;
ArrayList有三種構造方法:
ArrayList(); // 構造一個初始容量為10的空列表 ArrayList(int x); // 構造一個初始容量為x的空列表 ArrayList(Collection<? extends E> c); // 構造一個包含指定collection的元素的列表,這些元素是按照collection的迭代器返回它們的順序排列的?
下面用一個簡單的例子來介紹一下ArrayList的基本操作:
package com.tongye.holding;import java.util.ArrayList; import java.util.List; import java.util.Random;public class HoldObject { public static void main(String[] args){Random rand = new Random(47);Circle circle = new Circle();Square square = new Square();Triangle triangle = new Triangle();Rectangle rectangle = new Rectangle();// 創建List實例List<Integer> list1 = new ArrayList<Integer>(); // 創建一個只能存儲int類型對象的列表List<Shape> list2 = new ArrayList<Shape>(); // 創建一個只能存儲Shape類型對象的列表List list3 = new ArrayList(4); // 創建一個初始容量為4的列表,沒有指定存儲的類型 // 向列表list1中添加元素for(int i = 0;i < 10;i++)list1.add(rand.nextInt(20)); // add(E e)方法,將指定元素添加到此列表的尾部 for(Integer i : list1) // 所有的collection都可以用foreach進行遍歷System.out.print(i + " ");System.out.println("");// 用subList方法截取一部分list1的視圖List<Integer> list4 = list1.subList(3, 8); // subList(int fromIndex,int toIndex),返回列表中// 從fromIndex(包括)到toIndex(不包括)之間的部分視圖for(Integer i : list4) System.out.print(i + " ");System.out.println("");// 向列表list2中添加元素list2.add(circle); // 向列表中添加對象 list2.add(square);list2.add(triangle);list2.add(1,rectangle); // add(int index,E e)方法,向列表的指定位置插入指定元素 for(Shape i : list2) // 所有的collection都可以用foreach進行遍歷 System.out.println(i);System.out.println(list2.isEmpty()); // isEmpty()方法,檢查列表中是否有元素,沒有元素則返回trueSystem.out.println(list2.contains(circle)); // contains()方法用于檢查列表中是否含有指定元素,有則返回trueSystem.out.println(list2.indexOf(square)); // indexOf()方法,用于返回元素在列表中的索引號list2.get(1).showShape(); list2.remove(rectangle); // remove(Object o)方法,刪除列表中首次出現的指定元素list2.get(1).showShape();list2.remove(1);list2.get(1).showShape(); // remove(int index)方法,刪除列表中指定索引處的元素// 向list3中添加元素list3.add(100);list3.add("向列表中添加一個字符串");list3.add(rectangle);list3.add(1.048596);list3.add("容量自動增長");for(int i = 0;i < 5;i++)System.out.println(list3.get(i));} }class Shape{public void showShape(){System.out.println("Shape類");} }class Circle extends Shape{public void showShape(){System.out.println("Circle類");} }class Square extends Shape{public void showShape(){System.out.println("Square類");} }class Triangle extends Shape{public void showShape(){System.out.println("Triangle類");} }class Rectangle extends Shape{public void showShape(){System.out.println("Rectangle類");} } ArrayList CodeLinkedList:通過代價較低的在List中間進行的插入和刪除操作,提供了優化的順序訪問。LinkedList也和ArrayList一樣實現了基本的List接口,但是它在執行某些操作的時候比ArrayList更高效(在List中插入和刪除),但在隨機訪問操作方面卻要遜色一些。如果我們需要使用LinkedList,只需要在程序中修改List的實現即可,這也是使用接口的好處:
List<Integer> list ?= new LinkedList<Integer>(); // 用LinkedList來實現List
?
b)Set:不能有重復元素
Set是一個不包含重復元素的collection,更確切地講,Set不包含滿足 e1.equals(e2) 的元素對 e1和e2,并且最多包含一個null元素;Set具有和Collection完全一樣的接口,因此沒有任何額外的功能,實際上Set就是Collection,只是行為不同;它有三個實現:HashSet、TreeSet、LinkedHashSet.
①、HashSet:
HashSet是基于HashMap的一個set實現,它不保證set的迭代順序,特別是不保證該順序永久不變;
HashSet允許使用null元素;
HashSet為基本操作提供了穩定性能(add,remove,contains,size);
HashSet進行迭代所需的時間與HashSet實例的大小(元素的數量)和底層HashMap實例的“容量”成比例,因此如果迭代性能很重要,則不要講初始容量設置得太高(或將加載因子設置的太低);
HashSet是不同步的,在多線程中同時訪問一個HashSet時,需要使用同步語句來加鎖,可以使用 Collection.synchronizedSet方法來包裝set,最好在創建的時候完成這一步,一面對set進行意外的不同步訪問: ?Set s = Collections.synchronizedSet(new HashSet( ));
HashSet的iterator方法返回的迭代器是快速失敗的:在創建迭代器后,如果對set進行修改,除非通過迭代器自身的remove方法,否則在任何時間以任何方式對其進行修改,Iteractor都將拋出異常。
HashSet有四種構造方法:
HashSet(); // 創建一個空的set,其底層HashMap實例的默認初始容量是16,加載因子是0.75 HashSet(Collection<? extends E> c); // 創建一個包含指定collection中的元素的新set HashSet(int intialCapacity); // 創建一個具有指定初始容量和默認加載因子的set HashSet(int intialCapacity,float loadFactor); // 創建一個具有指定初始容量和加載因子的set?
②、TreeSet:
TreeSet是基于TreeMap的一個set實現;
TreeSet為基本操作提供受保證的時間開銷(add,remove,contains);
TreeSet使用元素的自然順序對元素進行排序,或根據創建元素時提供的Comparator進行排序,具體取決于使用的構造方法;
TreeSet是不同步的;
TreeSet的iterator方法返回的迭代器是快速失敗的;
TreeSet有四種構造方法:
TreeSet(); // 創建一個新的空set,該set根據其元素的自然順序進行排序 TreeSet(Collection<? extends E> c); // 創建一個包含指定collection元素的新的TreeSet,它按照其元素的自然順序進行排序 TreeSet(Compartor<? super E> compartor); // 創建一個新的空的TreeSet,它根據指定的比較器進行排序 TreeSet(SortedSet<E> s); // 創建一個與指定有序set具有相同映射關系和相同排序的新TreeSet?
③、LinkedHashSet:
LinkedHashSet是具有可預知迭代順序的set接口的哈希表和鏈接列表實現;
LinkedHashSet定義了迭代順序,即按照元素插入到set中的順序進行迭代,插入順序不受在set中重新插入的元素的影響;
LinkedHashSet迭代所需時間與set的大小成正比而與容量無關;
LinkedHashSet提供了所有可選的set操作,并且允許null元素;可以為基本操作提供穩定的性能;不同步;迭代器是快速失敗的
其構造方法與HashSet類似。
下面用一個簡單的例子介紹一下Set的基本操作:
package com.tongye.holding;import java.util.Random; import java.util.Set; import java.util.HashSet; import java.util.TreeSet;public class SetExample {public static void main(String[] args){Random rand = new Random(47);Set<Integer> hashSetInt = new HashSet<Integer>(); for(int i = 0;i < 100;i++)hashSetInt.add(rand.nextInt(20));System.out.println(hashSetInt);Set<Integer> treeSetInt = new TreeSet<Integer>();for(int i = 0;i < 100;i++)treeSetInt.add(rand.nextInt(20));System.out.println(treeSetInt);} } Set Code注:實際上,我在eclipse上運行上述代碼,發現無論是HashSet還是TreeSet,輸出的元素都是按自然順序排列的,查閱資料后發現可能是JDK版本的原因,JDK8中HashMap的實現有了一些變化,這些新特性導致了HashSet輸入整型數據時會按照自然順序進行排列。
?
c)Queue:按照排隊規則來確定對象產生的順序(通常與它們被插入的順序相同)
Queue(隊列)是一個典型的先進先出的容器,它有兩個實現 LinkedList以及PriorityQueue。LinkedList提供了方法以支持隊列的行為,并且實現了Queue接口;PriorityQueue(優先級隊列)聲明下一個彈出元素是最需要的元素(具有最高優先級)。
?
2)Map:保存一組成對的“鍵值對”對象,允許使用鍵來查找值
Map可用于將一個對象映射到其他對象上。Map接口提供三種collection視圖,允許以鍵集、值集或鍵-值映射關系集的形式查看某個映射的關系。映射順序為迭代器在映射collection視圖上返回其元素的順序。它有兩個實現:HashMap和TreeMap。
HashMap:
基于哈希表的Map實現,此實現提供所有可選的映射操作,并允許使用null值和null鍵;不保證映射的順序,特別是不保證該順序恒久不變。
構造方法:
HashMap(); // 創建一個具有默認初始容量(16)和默認加載因子(0.75)的空的HashMap HashMap(int initialCapacity); // 創建一個指定初始容量和默認加載因子的空的HashMap HashMap(int initialCapacity,float loadFactor); // 創建一個指定初始容量和指定加載因子的空的HashMap HashMap(Map<? extends K,? extends V> m); // 創建一個映射關系與指定Map相同的新的HashMapTreeMap:
基于紅黑樹的Map實現,該映射根據其鍵的自然順序進行排序,或根據創建映射時提供的Compartor進行排序,具體取決于使用的構造方法。
TreeMap(); //使用鍵的自然順序創建一個新的空的樹映射 TreeMap(Compartor<? super K> compartor); // 構造一個新的空的樹映射,該映射根據給定比較器進行排序 TreeMap(Map<? extends K,? extends V> m); // 構造一個與給定映射具有相同映射關系的新的樹映射,該映射根據其鍵的自然順序進行排序 TreeMap(SortedMap<K,? extends V> m); // 構造一個與指定有序映射具有相同映射關系和相同排序順序的新的樹映射下面用一個簡單的例子簡單介紹一下Map一些用法:
package com.tongye.holding;import java.util.HashMap; import java.util.Map; import java.util.Random;public class MapExample {public static void main(String[] args){Random rand = new Random(47);Map<Integer,Integer> mapInt = new HashMap<Integer,Integer>(); // 創建一個空的新的HashMapfor(int i = 0; i < 10000; i++){Integer key = rand.nextInt(20);Integer value = mapInt.get(key); // 返回該鍵所映射的值,如果該鍵還沒有任何映射關系,則返回nullmapInt.put(key, value == null? 1 : value + 1); // 在此映射中關聯指定值與指定鍵 }System.out.println(mapInt);} } Map Code?
轉載于:https://www.cnblogs.com/tongye/p/6782067.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的JAVA学习笔记--初识容器类库的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: #、%和$符号在OGNL表达式中的作用
- 下一篇: LinkedIn联合创始人:硅谷也就70