前言:在java開發中咱們離不開集合數組等,在java中有個專有名詞:「容器」 ,下面會結合Thinking in Java的知識和實際開發中業務場景講述一下容器在Web項目中的用法。可結合圖片代碼瞭解Java中的容器html
備註 :這個地方 ,參考於朝向遠方的博客Java容器詳解 ,既然前人總結的這麼好,我就直接拿來用,在這裏更注重在實際開發中的例子,感謝那些總結的前輩們,辛苦了。java
Thinking in Java 中並無把數組歸爲Java的容器,實際上數組的確不是Java獨有的c++ ,c都有數組。可是,在web開發時我仍是把數組歸類到容器中,由於他們說白了都是在作相同的事情c++
另外還有一個細節點就是:我翻遍了我開發過的項目,可是很驚訝的發現,這麼多項目裏直接用數組存儲對象極爲少見。想一想也是,java是面向對象的,而數組對java總歸是有點偏底層。web
珍惜這來之不易的demo吧: 算法
public Map<String, String> getDimValue() { if (this.dimValue != null) return dimValue; this.dimValue = new HashMap<String, String>(); if (this.dim != null && this.dim.length() != 0) { String[] strDims = this.dim.split(",");//能夠用截取的方式,獲得String[] for (String s : strDims) { String[] dims = s.split("\\:"); this.dimValue.put(dims[0], dims[1]);//數組訪問經過下標,可是注意 最多到array[array.length-1],越界直接拋出異常,和c++不同 } } return this.dimValue; }
數組(array)是最多見的數據結構。數組是相同類型元素的有序集合,並有固定的大小(可容納固定數目的元素)。數組能夠根據下標(index)來隨機存取(random access)元素。在內存中,數組一般是一段連續的存儲單元。spring
Java支持數組這一數據結構。咱們須要說明每一個數組的類型和大小,java利用byte[] 能夠表示blob字段,存放圖片,xml,json等。String[]則能夠用來存一些字符串,id, code等。 json
//web項目中卻是經常使用 byte[]來存放blob字段等
@Type(type = "org.springframework.orm.hibernate3.support.BlobByteArrayType") private byte[] globals;
在說明類型時,在類型說明(String)後面增長一個[],來講明是一個數組。使用new建立容器時,須要說明數組的大小;或者是 直接 int a = {1,2,3} 這樣直接用{}同時初始化。 api
數組能夠經過遍歷的形式轉爲其餘容器類型,可是其餘類型能夠經過 toArray()快速轉爲數組(下文中會說到Arrays這個工具類能夠把數組轉爲List)數組
在開發中,Collection最經常使用的就是兩個類: Set和List。由於同屬於一個Collection下,相互轉化方便,調用的方法也相似。(collection Api)數據結構
Java中經常使用方法接口:
* boolean add(Object obj): 添加對象,集合發生變化則返回true
* Iterator iterator():返回Iterator接口的對象 * int size() * boolean isEmpty() * boolean contains(Object obj) * void clear() * <T> T[] toArray(T[] a)
上述接口參照於:wishyouhappy的博客:java容器總結。
具體能夠查看list中文文檔,文檔中清楚的描述到List<E>是一個實現了 Collection的接口,而咱們能夠直接用List 聲明對象(接口能夠直接聲明一個對象)。容器的引用爲List類型,但容器的實現爲ArrayList類。這裏是將接口與實現類分離。事實上,同一種抽象數據結構(ADT)均可以有多種實施方法(好比棧能夠實施爲數組和鏈表)。這樣的分離容許咱們更自由的選擇ADT的實施方式(參考於Java容器詳解)
java中較爲經常使用的 ArrayList,LinkedList, 集合中的元素能夠相等,是有順序的
1 public class Test {
2 public static void main(String[] args) { 3 List<String> list = new ArrayList<String>(); 4 //添加單個元素 5 for(String s1:"hehe wo shi lao da".split(" ")){ 6 list.add(s1); 7 } 8 //添加多個元素 9 list.addAll(Arrays.asList("nan dao ni bu xin?".split(" ")));//Arrays是一個工具類,能夠幫助咱們少些遍歷代碼 10 System.out.println(list.toString());//list重寫了toString方法,輸出list中每個元素 11 //修改位置爲i的元素 12 for(int i = 0; i<list.size();i++){ 13 list.set(i, "u"); 14 } 15 System.out.println(list.toString()); 16 list.removeAll(Arrays.asList(new String[]{"u"}));//這個地方爲了測試 我初始化了一個字符數組 new String[]{"u"} 17 System.out.println(list.toString());18 19 } 20 }
上邊的代碼只是爲了說明 list的主要用途,實際上開發中可能用不到這麼多,比較經常使用的也就
List中 還有一個實習類 LinkedList 比較經常使用,它能夠用來作隊列 的實現,也能夠變相完成棧的工做。
主要方法有:
ListedList採用的是鏈式存儲。鏈式存儲就會定一個節點Node。包括三部分前驅節點、後繼節點以及data值。因此存儲存儲的時候他的物理地址不必定是連續的
具體內容可參照java提升篇(二二)---LinkedList 下面列出了linkedList的部分源碼(不建議一開始就看)
集合(set)也是元素的集合。集合中不容許有等值的元素,集合的元素沒有順序:
咱們用Set多數時候是利用它的特性,沒有重複的元素,例如:
2.1 HashSet:HashSet查詢速度比較快,可是存儲的元素是隨機的並無排序
public class Test
{
public static void main(String[] args) { Set<Integer> s1 = new HashSet<Integer>(); s1.add(4); s1.add(5); s1.add(4); s1.remove(5); System.out.println(s1); System.out.println(s1.size()); } }
咱們能夠用它去過濾重複數據,Set 能夠輕鬆的轉爲List,由於構造方法傳入參數是Collection<? extends E> c
1 Set<String> set = new HashSet<String>();
2 set.add("h"); 3 set.add("h"); 4 List<String> fromSets = new ArrayList<String>(set); 5 System.out.println(fromSets.toString()); 6 Set<String> s1 = new HashSet<String>(fromSets); 7 System.out.println(s1.toString());
這個地方,很是有意思的是,HashSet中居然持有的是HashMap,利用HashMap存取數據
public HashSet(Collection<? extends E> c) {
map = new HashMap<E,Object>(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); }
HashSet只有add方法,沒有get方法(這和list稍微不一樣)。可是HashSet 實現了Iterator<E> iterator()。能夠經過Iterator遍歷,具體能夠查看Set中文文檔
2.2:TreeSet
TreeSet是將元素存儲紅-黑樹結構中,因此存儲的結果是有順序的
public static void main(String[] args){
Random random=new Random(47); Set<Integer> intset=new TreeSet<Integer>(); for (int i=0;i<10000;i++){ intset.add(random.nextInt(30)); } System.out.print(intset); }
3:collection中的Iterator
public class Test
{
public static void main(String[] args) { List<Integer> l1 = new ArrayList<Integer>(); l1.add(4); l1.add(5); l1.add(2); Iterator i = l1.iterator(); while(i.hasNext()) { System.out.println(i.next()); } } }
Collection能夠用foreach,由於其實現了Iterator接口
public class IteratorClass {
public Iterator<String> iterator(){ return new Itr(); } private class Itr implements Iterator<String>{ protected String[] words=("Hello Java").split(" "); private int index=0; public boolean hasNext() { return index<words.length; } public String next() { return words[index++]; } public void remove() { } } }
foreach循環最終也會轉化爲Iterator遍歷 (Iterator it=iterator;iterators.hasNext();)
Iterator iterators=new IteratorClass().iterator();
for (Iterator it=iterator;iterators.hasNext();) { System.out.println(iterators.next()); } while (iterators.hasNext()){ System.out.println(iterators.next()); }
下面說一下Java中極容易出錯的點:
for 循環查找集合中某個元素並刪除:極容易出現java.util.ConcurrentModificationException
List<String> list = new ArrayList<String>();
list.addAll(Arrays.asList("nan dao ni bu xin?".split(" "))); for(String st:list){ System.out.println(st); if(st.equals("ni")){ list.remove(st); } }
解決方式是將數組轉化爲Iterator,而後利用it.remove();刪除數組中的元素
public static void main(String[] args) {
List<String> list=new ArrayList<String>(); list.add("a"); list.add("bb"); list.add("a22"); Iterator<String> it=list.iterator(); //去除數組中"a"的元素 while(it.hasNext()){ String st=it.next(); if(st.equals("a")){ it.remove(); } } }
在web項目中,Map是很是經常使用的,固然在不少時候,Map會被一些包裝類給替代掉(這其實是敏捷開發中提到用vo替換map).可是Map仍是沒法阻擋的容器一哥。
Java中經常使用的方法接口
* Object get(Object key)
* Object put(Object key, Object value) * Set keySet() : returns the keys set Set<K> keySet() * Set entrySet(): returns mappings set Set<Map.Entry<K,V>> entrySet() * containsKey() * containsValue()
Map是鍵值對的集合。Map中的每一個元素是一個鍵值對,即一個鍵(key)和它對應的對象值(value)。對於Map容器,咱們能夠經過鍵來找到對應的對象。
哈希表是Map常見的一種實現方式,也是實際開發中用的最普遍的 (HashMap),想要具體瞭解HashMap的原理,能夠參考 hashmap實現原理淺析
public class Test
{
public static void main(String[] args) { Map<String, Integer> m1 = new HashMap<String, Integer>(); m1.put("Vamei", 12); m1.put("Jerry", 5); m1.put("Tom", 18); System.out.println(m1.get("Vamei")); } }
在Map中,咱們使用put()方法來添加元素,用get()方法來得到元素。
Map還提供了下面的方法,來返回一個Collection:
java中有一些工具類來幫助咱們處理容器相關的內容。好比Arrays,java中的一些類都有用到這些工具類
ArrayList源碼中的clone方法
/**
* Returns a shallow copy of this <tt>ArrayList</tt> instance. (The
* elements themselves are not copied.)
*
* @return a clone of this <tt>ArrayList</tt> instance
*/
public Object clone() {
try { ArrayList<E> v = (ArrayList<E>) super.clone(); v.elementData = Arrays.copyOf(elementData, size); v.modCount = 0; return v; } catch (CloneNotSupportedException e) { // this shouldn't happen, since we are Cloneable throw new InternalError(); } }
ArrayList源碼中的 toArray()方法
public Object[] toArray() {
return Arrays.copyOf(elementData, size); }
若是你對Arrays這個工具類有興趣,能夠看一下源碼,它最終調用到了本地方法(摺疊起來,是不但願給讀者帶來困惑)
Arrays的一些其餘方法:
再好比Collections:
能夠參考thinking in java之Collections工具類的使用
max():取集合的最大元素
subList():截取list
addAll():添加集合
有興趣的能夠去看一下源碼,我以爲很是有幫助