1. 程式人生 > >Java的容器類

Java的容器類

bool 移除 art ctc not IV 自動包裝 boolean 規則

程序總是根據運行時才知道的某些條件去創建新對象。需要在任意時刻和任意位置創建任意數量的對象。

如果你想保存一組基本數據類型數據,建議使用數組,但是數組有固定的尺寸。
一般情況下,你在寫程序時並不知道將需要多少個對象,或者是否需要更復雜的方式來存儲對象。
Java實用類庫提供了一套完整的容器類來解決這個問題,其中基本的類型是ListSetQueueMap。這些對象類型也稱為集合類容器提供了完善的方法來保存對象

下面是完整的容器分類圖:
技術分享圖片

1.基本概念

Java容器類類庫的用途是“保存對象”,並將其劃分為兩個不同的概念:

  1. Collection。一個獨立元素的序列。List必須按照插入的順序保存元素,而Set
    不能有重復元素。Queue按照排隊規則來確定對象產生的順序。
  2. Map。一組成對的“鍵值對”對象,允許你使用鍵來查找值。
//在創建的時候指定所使用的精確類型。
List<Apple> apples = new ArrayList<Apple>();
//註意:ArrayList已經被向上轉型為List。使用接口的目的在於如果你決定去修改你的實現,你所需要的只是在創建出修改它。
//List<Apple> apples = new LinkedList<Apple>();
import java.util.*;

public class SimpleCollection {
    //用Integer對象填充了一個Collection,然後打印所產生的容器中的所有元素。
public static void main(String[] args) { Collection<Integer> c = new ArrayList<Integer>(); for(int i = 0; i < 10; i++){ c.add(i); // Autoboxing } for(Integer i : c){ System.out.print(i + ", "); } } } /* Output:
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, */

添加一組元素

import java.util.*;

public class AddingGroups {
    public static void main(String[] args) {
        Collection<Integer> collection = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5));
        Integer[] moreInts = { 6, 7, 8, 9, 10 };
        collection.addAll(Arrays.asList(moreInts));
        // Runs significantly faster, but you can't
        // construct a Collection this way:
        Collections.addAll(collection, 11, 12, 13, 14, 15);
        Collections.addAll(collection, moreInts);
        // Produces a list "backed by" an array:
        List<Integer> list = Arrays.asList(16, 17, 18, 19, 20);
        list.set(1, 99); // OK -- modify an element, list的值為 [16, 99, 18, 19, 20]
        // list.add(21); // Runtime error because the underlying array cannot be resized.
    }
}
//在java.util包中的Arrays和Collections類中都有很多實用方法,可以在一個Collection中添加一組元素。
//Arrays.asLisst()方法接受一個數組或是一個用逗號分隔的元素列表(實用可變參數),並將其轉換為一個List對象。

2.容器的打印

你必須使用Arrays.toString()來產生數組的可打印表示,但是打印容器無需任何幫助。

import java.util.*;

@SuppressWarnings("rawtypes")
public class PrintingContainers {
    
    
    static Collection fill(Collection<String> collection) {
        collection.add("rat");
        collection.add("cat");
        collection.add("dog");
        collection.add("dog");
        return collection;
    }
    
    static Map fill(Map<String,String> map) {
        map.put("rat", "Fuzzy");
        map.put("cat", "Rags");
        map.put("dog", "Bosco");
        map.put("dog", "Spot");
        return map;
    }
    
    public static void main(String[] args) {
        System.out.println(fill(new ArrayList<String>()));
        System.out.println(fill(new LinkedList<String>()));
        System.out.println(fill(new HashSet<String>()));
        System.out.println(fill(new TreeSet<String>()));
        System.out.println(fill(new LinkedHashSet<String>()));
        System.out.println(fill(new HashMap<String,String>()));
        System.out.println(fill(new TreeMap<String,String>()));
        System.out.println(fill(new LinkedHashMap<String,String>()));
    }
}
/* Output:
[rat, cat, dog, dog]
[rat, cat, dog, dog]
[rat, cat, dog]
[cat, dog, rat]
[rat, cat, dog]
{rat=Fuzzy, cat=Rags, dog=Spot}
{cat=Rags, dog=Spot, rat=Fuzzy}
{rat=Fuzzy, cat=Rags, dog=Spot}
*/

3.List

有兩種類型的List

  • 基本的ArrayList,它長於隨機訪問元素,但是在List的中間插入和移除元素時較慢。
  • LinkedList,它通過代價較低的在List中間進行的插入和刪除操作,提供了優化的順序訪問。

技術分享圖片

List的功能方法
技術分享圖片

4.Set

Set不保存重復的元素。

import java.util.*;

public class SetOfInteger {
    public static void main(String[] args) {
        Random rand = new Random(47);
        Set<Integer> intset = new HashSet<Integer>();
        for(int i = 0; i < 10000; i++)
            intset.add(rand.nextInt(30));
        System.out.println(intset);
    }
}

5.Map

import java.util.*;

public class Statistics {
    
    public static void main(String[] args) {
        
        Random rand = new Random(47);
        Map<Integer,Integer> m = new HashMap<Integer,Integer>();
        for(int i = 0; i < 10000; i++) {
            // Produce a number between 0 and 20:
            int r = rand.nextInt(20);
            Integer freq = m.get(r);
            //自動包裝機制將隨機生成的int轉換為HashMap可以使用的Integer引用。
            m.put(r, freq == null ? 1 : freq + 1);
        }
        System.out.println(m);
    }
}
/* Output:
{0=481, 1=502, 2=489, 3=508, 4=481, 5=503, 6=519, 7=471, 8=468, 9=549, 10=513, 11=531, 12=521, 13=506, 14=477, 15=497, 16=533, 17=509, 18=478, 19=464}
*/
//鍵是由Random產生的數字,而值是該數字出現的次數。

6.Collection和Iterator

Collection是描述所有序列容器的共性的根接口。
java.util.AbstractCollection類提供了Collection的默認實現。
使用接口描述的一個理由是它可以使我們能夠創建更通用的代碼。

Collection的功能方法:
技術分享圖片

叠代器

import typeinfo.pets.*;
import java.util.*;

public class SimpleIteration {
    public static void main(String[] args) {
        List<Pet> pets = Pets.arrayList(12);
        //實現Collection就意味著需要提供iterator()方法。
        Iterator<Pet> it = pets.iterator();
        while(it.hasNext()) {
            Pet p = it.next();
            System.out.print(p.id() + ":" + p + " ");
        }
        System.out.println();
        
        //foreach語法主要用於數組,但是它也可以應用於任何Collection對象。
        // A simpler approach, when possible:
        for(Pet p : pets){
            System.out.print(p.id() + ":" + p + " ");
        }
        System.out.println();
        
        // An Iterator can also remove elements:
        it = pets.iterator();
        for(int i = 0; i < 6; i++) {
            it.next();
            it.remove();
        }
        System.out.println(pets);
    }
}
/* Output:
0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx 8:Cymric 9:Rat 10:EgyptianMau 11:Hamster
0:Rat 1:Manx 2:Cymric 3:Mutt 4:Pug 5:Cymric 6:Pug 7:Manx 8:Cymric 9:Rat 10:EgyptianMau 11:Hamster
[Pug, Manx, Cymric, Rat, EgyptianMau, Hamster]
*/

Java SE5引入了新的被稱為Iterable的接口,該接口包含一個能夠產生Iteratoriterator()方法,並且Iterable接口被foreach用來在序列中移動。
因此,如果你創建任何實現Iterable的類,都可以將它用於foreach語句中。

import java.util.*;

public class IterableClass implements Iterable<String> {
    protected String[] words = ("And that is how we know the Earth to be banana-shaped.").split(" ");
    
    public Iterator<String> iterator() {
        return new Iterator<String>() {
            private int index = 0;
            public boolean hasNext() {
                return index < words.length;
            }
            public String next() { return words[index++]; }
            public void remove() { // Not implemented
                throw new UnsupportedOperationException();
            }
        };
    }
    
    public static void main(String[] args) {
        for(String s : new IterableClass())
            System.out.print(s + " ");
    }
}
/* Output:
And that is how we know the Earth to be banana-shaped.
*/

Java SE5中,大量的類都是Iterable類型,主要包括所有的Collection類(但是不包括各種Map)。

7.散列與散列碼

ObjecthashCode()方法默認是使用對象的地址計算散列碼,equals()方法默認是比較對象的地址。
如果要使用自己的類作為HashMap的鍵,必須同時重載hashCode()equals()

相關閱讀:到底什麽是hash?

Java的容器類