java集合容器

3.3 集合

  • 一方面, 面向?qū)ο笳Z(yǔ)言對(duì)事物的體現(xiàn)都是以對(duì)象的形式,為了方便對(duì)多個(gè)對(duì)象的操作,就要對(duì)對(duì)象進(jìn)行存儲(chǔ)。另一方面,使用Array存儲(chǔ)對(duì)象方面具有一些弊端,而Java 集合就像一種容器,可以動(dòng)態(tài)地把多個(gè)對(duì)象的引用放入容器中。
  • Java 集合類(lèi)可以用于存儲(chǔ)數(shù)量不等的多個(gè)對(duì)象,還可用于保存具有映射關(guān)系的關(guān)聯(lián)數(shù)組。

Java 集合可分為 Collection 和 Map 兩種體系

  • Collection接口:
  • Set:元素?zé)o序、不可重復(fù)的集合 ---類(lèi)似高中的“集合”
  • List:元素有序,可重復(fù)的集合 ---”動(dòng)態(tài)”數(shù)組
  • Map接口:具有映射關(guān)系“key-value對(duì)”的集合 ---類(lèi)似于高中的“函數(shù)” y = f(x) (x1,y1) (x2,y2)

3.3.1 Collection接口

  • Collection 接口是 List、Set 和 Queue 接口的父接口,該接口里定義的方法既可用于操作 Set 集合,也可用于操作 List 和 Queue 集合。
  • JDK不提供此接口的任何直接實(shí)現(xiàn),而是提供更具體的子接口(如:Set和List)實(shí)現(xiàn)。
  • 在 Java5 之前,Java 集合會(huì)丟失容器中所有對(duì)象的數(shù)據(jù)類(lèi)型,把所有對(duì)象都當(dāng)成 Object 類(lèi)型處理;從 Java5 增加了泛型以后,Java 集合可以記住容器中對(duì)象的數(shù)據(jù)類(lèi)型

Collection接口繼承樹(shù)


集合中數(shù)組間轉(zhuǎn)換操作:

方法類(lèi)型 方法
Object[] toArray() 返回包含此collection中所有元素的數(shù)組
<T> T[] toArray(T[] a) 返回包含此 collection中所有元素的數(shù)組;返回?cái)?shù)組的運(yùn)行時(shí)類(lèi)型與指定數(shù)組的運(yùn)行時(shí)類(lèi)型相同

3.3.1.1 Iterator接口

  • Iterator對(duì)象稱(chēng)為迭代器(設(shè)計(jì)模式的一種),主要用于遍歷 Collection 集合中的元素。
  • 所有實(shí)現(xiàn)了Collection接口的集合類(lèi)都有一個(gè)iterator()方法,用以返回一個(gè)實(shí)現(xiàn)了Iterator接口的對(duì)象。
  • Iterator 僅用于遍歷集合,Iterator 本身并不提供承裝對(duì)象的能力。如果需要?jiǎng)?chuàng)建 Iterator 對(duì)象,則必須有一個(gè)被迭代的集合。

Iterator接口方法:

在調(diào)用iterator.next()方法之前必須要調(diào)用iterator.hasNext()進(jìn)行檢測(cè)。
若不調(diào)用,且下一條記錄無(wú)效,直接調(diào)用iterator.next()會(huì)拋出NoSuchElementException異常。

//List的知識(shí)將在下面講到。這里先做演示
List l=new ArrayList();
//因?yàn)镃ollection framework只能存儲(chǔ)對(duì)象所以new封裝類(lèi)
l.add(new Integer(1));
l.add(new Integer(2));
l.add(new Integer(3));
l.add(new Integer(4));
Iterator x = l.iterator();

while(x.hasNext()){
   Object o = x.next();
   System.out.println(o);
}

輸出結(jié)果:

1
2
3
4

java5中提供了foreach循環(huán)迭代訪問(wèn)Collection

代碼示例

class Persons{
    public String name ;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    Persons(){
    }
    Persons(String name){
        this.name = name;
    }
    public static void main(String[] args) {
        List<Persons> persons  = new ArrayList<Persons>();
        persons.add(new Persons("張三"));
        persons.add(new Persons("李四"));
        persons.add(new Persons("王五"));
        persons.add(new Persons("趙六"));
        
        for(Persons person: persons){
            System.out.println(person.getName());
        }
        //其中:  
        //Persons 代表要遍歷的元素類(lèi)型
        //person 代表遍歷后元素名稱(chēng)
        //persons 代表要遍歷的元素名稱(chēng)
    }
}

輸出結(jié)果:

張三
李四
王五
趙六

3.3.1.2 List接口

  • Java中數(shù)組用來(lái)存儲(chǔ)數(shù)據(jù)的局限性
  • List集合類(lèi)中元素有序、且可重復(fù),集合中的每個(gè)元素都有其對(duì)應(yīng)的順序索引。
  • List容器中的元素都對(duì)應(yīng)一個(gè)整數(shù)型的序號(hào)記載其在容器中的位置,可以根據(jù)序號(hào)存取容器中的元素。
  • JDK API中List接口的實(shí)現(xiàn)類(lèi)常用的有:ArrayList、LinkedList和Vector。
  • List 集合里添加了一些根據(jù)索引來(lái)操作集合元素的方法
  • void add(int index, Object ele)
  • boolean addAll(int index, Collection eles)
  • Object get(int index)
  • int indexOf(Object obj)
  • int lastIndexOf(Object obj)
  • Object remove(int index)
  • Object set(int index, Object ele)
  • List subList(int fromIndex, int toIndex)

ArrayList

  • ArrayList 是 List 接口的典型實(shí)現(xiàn)類(lèi)
  • 本質(zhì)上,ArrayList是對(duì)象引用的一個(gè)變長(zhǎng)數(shù)組
  • ArrayList 是線程不安全的,而 Vector 是線程安全的,即使為保證 List 集合線程安全,也不推薦使用Vector
  • Arrays.asList(…) 方法返回的 List 集合既不是 ArrayList 實(shí)例,也不是 Vector 實(shí)例。Arrays.asList(…) 返回值是一個(gè)固定長(zhǎng)度的 List 集合

LinkedList

  • 對(duì)于頻繁的插入或刪除元素的操作,建議使用LinkedList類(lèi),效率較高

  • 新增方法:

           void addFirst(Object obj)
           void addLast(Object obj)   
           Object getFirst()
           Object getLast()
           Object removeFirst()
           Object removeLast()
    

代碼示例

        // List 接口的鏈接列表實(shí)現(xiàn)
        LinkedList<String> list = new LinkedList<String>();
        
        list.push("one");
        list.push("two");
        list.push("three");
        list.push("four");
        
        Iterator<String> lit = list.iterator();
        while (lit.hasNext()) {
            System.out.println(list.pop());
        }
        
        System.out.println(list.size() + "---------");

輸出結(jié)果:

four
three
two
one
0---------

Vector

  • Vector 是一個(gè)古老的集合,JDK1.0就有了。大多數(shù)操作與ArrayList相同,區(qū)別之處在于Vector是線程安全的。

  • 在各種list中,最好把ArrayList作為缺省選擇。當(dāng)插入、刪除頻繁時(shí),使用LinkedList;Vector總是比ArrayList慢,所以盡量避免使用。

  • 新增方法:

  • void addElement(Object obj)

  • void insertElementAt(Object obj,int index)

  • void setElementAt(Object obj,int index)

  • void removeElement(Object obj)

  • void removeAllElements()

代碼示例

Vector<String> v = new Vector<String>();// 10

// 同步
v.add("one");
v.add("two");
v.add("three");
v.add("one");
v.add("two");
v.add("three");

for (int i = 0; i < v.size(); i++) {
    System.out.print(v.get(i)+" ");
}
System.out.println("v.size() = "+v.size());

System.out.println("使用insertElementAt方法");
v.insertElementAt("啊哈", 0);
for (int i = 0; i < v.size(); i++) {
    System.out.print(v.get(i)+" ");
}
System.out.println("v.size() = "+v.size());

System.out.println("使用remove方法");
v.remove(0);
for (int i = 0; i < v.size(); i++) {
    System.out.print(v.get(i)+" ");
}
System.out.println("v.size() = "+v.size());

System.out.println("使用removeAllElements方法");
v.removeAllElements();
for (int i = 0; i < v.size(); i++) {
    System.out.print(v.get(i)+" ");
}
System.out.println("v.size() = "+v.size());

輸出結(jié)果:

one two three one two three v.size() = 6
使用insertElementAt方法
啊哈 one two three one two three v.size() = 7
使用remove方法
one two three one two three v.size() = 6
使用removeAllElements方法
v.size() = 0

LinkedList、ArrayList和Vector區(qū)別

1.ArrayList是最常用的List實(shí)現(xiàn)類(lèi),內(nèi)部是通過(guò)數(shù)組實(shí)現(xiàn)的,它允許對(duì)元素進(jìn)行快速隨機(jī)訪問(wèn)。數(shù)組的缺點(diǎn)是每個(gè)元素之間不能有間隔,當(dāng)數(shù)組大小不滿足時(shí)需要增加存儲(chǔ)能力,就要講已經(jīng)有數(shù)組的數(shù)據(jù)復(fù)制到新的存儲(chǔ)空間中。當(dāng)從ArrayList的中間位置插入或者刪除元素時(shí),需要對(duì)數(shù)組進(jìn)行復(fù)制、移動(dòng)、代價(jià)比較高。因此,它適合隨機(jī)查找和遍歷,不適合插入和刪除。

2.Vector與ArrayList一樣,也是通過(guò)數(shù)組實(shí)現(xiàn)的,不同的是它支持線程的同步,即某一時(shí)刻只有一個(gè)線程能夠?qū)慥ector,避免多線程同時(shí)寫(xiě)而引起的不一致性,但實(shí)現(xiàn)同步需要很高的花費(fèi),因此,訪問(wèn)它比訪問(wèn)ArrayList慢。

3.LinkedList是用鏈表結(jié)構(gòu)存儲(chǔ)數(shù)據(jù)的,很適合數(shù)據(jù)的動(dòng)態(tài)插入和刪除,隨機(jī)訪問(wèn)和遍歷速度比較慢。另外,他還提供了List接口中沒(méi)有定義的方法,專(zhuān)門(mén)用于操作表頭和表尾元素,可以當(dāng)作堆棧、隊(duì)列和雙向隊(duì)列使用。

ArrayList和Vector的區(qū)別。

一.同步性:Vector是線程安全的,也就是說(shuō)是同步的,而ArrayList是線程序不安全的,不是同步的
二.數(shù)據(jù)增長(zhǎng):當(dāng)需要增長(zhǎng)時(shí),Vector默認(rèn)增長(zhǎng)為原來(lái)一培,而ArrayList卻是原來(lái)的一半

ArrayList 默認(rèn)量:0 -10  增量 原來(lái)一半   
Vector  默認(rèn)量: 10 增量 原來(lái)的一倍。

拓展了解:ListIterator接口

  • List 額外提供了一個(gè) listIterator() 方法,該方法返回一個(gè) ListIterator 對(duì)象, ListIterator 接口繼承了 Iterator 接口,提供了專(zhuān)門(mén)操作 List 的方法:
  • void add()
  • boolean hasPrevious()
  • Object previous()
  • Boolean hasNext()
  • Object next()

Iterator和ListIterator主要區(qū)別
一、ListIterator和Iterator都有hasNext()和next()方法,可以實(shí)現(xiàn)順序向后遍歷。但是ListIterator有hasPrevious()和previous()方法,可以實(shí)現(xiàn)逆向(順序向前)遍歷。Iterator就不可以。
二、ListIterator可以定位當(dāng)前的索引位置,nextIndex()和previousIndex()可以實(shí)現(xiàn)。Iterator 沒(méi)有此功能。
三、ListIterator有add()方法,可以向List中插入對(duì)象,而Iterator不能。
四、都可實(shí)現(xiàn)刪除對(duì)象,但是ListIterator可以實(shí)現(xiàn)對(duì)象的修改,set()方法可以實(shí)現(xiàn)。Iterator僅能遍歷,不能修改。因?yàn)長(zhǎng)istIterator的這些功能,可以實(shí)現(xiàn)對(duì)LinkedList等List數(shù)據(jù)結(jié)構(gòu)的操作。

3.3.1.3 Set接口

  • Set接口是Collection的子接口,set接口沒(méi)有提供額外的方法
  • Set 集合不允許包含相同的元素,如果試把兩個(gè)相同的元素加入同一個(gè) Set 集合中,則添加操作失敗。
  • Set 判斷兩個(gè)對(duì)象是否相同不是使用 == 運(yùn)算符,而是根據(jù) equals 方法

Set實(shí)現(xiàn)類(lèi)之一 HashSet

  • HashSet 是 Set 接口的典型實(shí)現(xiàn),大多數(shù)時(shí)候使用 Set 集合時(shí)都使用這個(gè)實(shí)現(xiàn)類(lèi)。
  • HashSet 按 Hash 算法來(lái)存儲(chǔ)集合中的元素,因此具有很好的存取和查找性能。
  • HashSet 具有以下特點(diǎn):
  • 不能保證元素的排列順序
  • HashSet 不是線程安全的
  • 集合元素可以是 null
  • 當(dāng)向 HashSet 集合中存入一個(gè)元素時(shí),HashSet 會(huì)調(diào)用該對(duì)象的 hashCode() 方法來(lái)得到該對(duì)象的 hashCode 值,然后根據(jù) hashCode 值決定該對(duì)象在 HashSet 中的存儲(chǔ)位置。
  • HashSet 集合判斷兩個(gè)元素相等的標(biāo)準(zhǔn):兩個(gè)對(duì)象通過(guò) hashCode() 方法比較相等,并且兩個(gè)對(duì)象的 equals() 方法返回值也相等。

代碼示例

Set<String> set = new HashSet<String>();// ctrl+shift+O
set.add("one");
set.add("one");
set.add("two");
set.add("three");
set.add("four");
/*
 * for(int i=0;i<set.size();i++){ set. }
 */
System.out.println("長(zhǎng)度:" + set.size());

Iterator<String> it = set.iterator();

while (it.hasNext()) {
    System.out.println(it.next());
}

輸出結(jié)果:

長(zhǎng)度:4
four
one
two
three

HashCode()

  • 如果兩個(gè)元素的 equals() 方法返回 true,但它們的 hashCode() 返回值不相等,hashSet 將會(huì)把它們存儲(chǔ)在不同的位置,但依然可以添加成功。
  • 對(duì)于存放在Set容器中的對(duì)象,對(duì)應(yīng)的類(lèi)一定要重寫(xiě)equals()和hashCode(Object obj)方法,以實(shí)現(xiàn)對(duì)象相等規(guī)則。
  • 重寫(xiě) hashCode() 方法的基本原則:
  • 在程序運(yùn)行時(shí),同一個(gè)對(duì)象多次調(diào)用 hashCode() 方法應(yīng)該返回相同的值
  • 當(dāng)兩個(gè)對(duì)象的 equals() 方法比較返回 true 時(shí),這兩個(gè)對(duì)象的 hashCode() 方法的返回值也應(yīng)相等
  • 對(duì)象中用作 equals() 方法比較的 Field,都應(yīng)該用來(lái)計(jì)算 hashCode 值

Set實(shí)現(xiàn)類(lèi)之二 LinkedHashSet

  • LinkedHashSet 是 HashSet 的子類(lèi)
  • LinkedHashSet 根據(jù)元素的 hashCode 值來(lái)決定元素的存儲(chǔ)位置,但它同時(shí)使用鏈表維護(hù)元素的次序,這使得元素看起來(lái)是以插入順序保存的。
  • LinkedHashSet插入性能略低于 HashSet,但在迭代訪問(wèn) Set 里的全部元素時(shí)有很好的性能。
  • LinkedHashSet 不允許集合元素重復(fù)。

代碼示例

Set<String> set = new LinkedHashSet<String>();// ctrl+shift+O
set.add("one");
set.add("two");
set.add("three");
set.add("four");
set.add("four");
/*
 * for(int i=0;i<set.size();i++){ set. }
 */
System.out.println("長(zhǎng)度:" + set.size());

Iterator<String> it = set.iterator();

while (it.hasNext()) {
    System.out.println(it.next());
}

輸出結(jié)果:

長(zhǎng)度:4
one
four
two
three

Set實(shí)現(xiàn)類(lèi)之三 TreeSet

  • TreeSet 是 SortedSet 接口的實(shí)現(xiàn)類(lèi),TreeSet 可以確保集合元素處于排序狀態(tài)。
  • Comparator comparator()
  • Object first()
  • Object last()
  • Object lower(Object e)
  • Object higher(Object e)
  • SortedSet subSet(fromElement, toElement)
  • SortedSet headSet(toElement)
  • SortedSet tailSet(fromElement)
  • TreeSet 兩種排序方法:自然排序和定制排序。默認(rèn)情況下,TreeSet 采用自然排序。

案例5

public static void main(String[] args) {
    //創(chuàng)建對(duì)象
    TreeSet<String> set = new TreeSet<String>();
    //添加數(shù)據(jù)
    set.add("f");
    set.add("y");
    set.add("A");
    set.add("Z");
    System.out.println("長(zhǎng)度   "+set.size());
    System.out.println("第一個(gè)元素:"+set.first());
    System.out.println("最后個(gè)元素:"+set.last());
    System.out.println("--------------------");
    Iterator<String> it = set.iterator();
    while(it.hasNext()){
        System.out.println(it.next());
    }
}

輸出結(jié)果:

長(zhǎng)度   4
第一個(gè)元素:A
最后個(gè)元素:y
--------------------
A
Z
f
y   

自然排序

  • 自然排序:TreeSet 會(huì)調(diào)用集合元素的 compareTo(Object obj) 方法來(lái)比較元素之間的大小關(guān)系,然后將集合元素按升序排列
  • 如果試圖把一個(gè)對(duì)象添加到 TreeSet 時(shí),則該對(duì)象的類(lèi)必須實(shí)現(xiàn) Comparable 接口。
  • 實(shí)現(xiàn) Comparable 的類(lèi)必須實(shí)現(xiàn) compareTo(Object obj) 方法,兩個(gè)對(duì)象即通過(guò) compareTo(Object obj) 方法的返回值來(lái)比較大小。
  • Comparable 的典型實(shí)現(xiàn):
  • BigDecimal、BigInteger 以及所有的數(shù)值型對(duì)應(yīng)的包裝類(lèi):按它們對(duì)應(yīng)的數(shù)值大小進(jìn)行比較
  • Character:按字符的 unicode值來(lái)進(jìn)行比較
  • Boolean:true 對(duì)應(yīng)的包裝類(lèi)實(shí)例大于 false 對(duì)應(yīng)的包裝類(lèi)實(shí)例
  • String:按字符串中字符的 unicode 值進(jìn)行比較
  • Date、Time:后邊的時(shí)間、日期比前面的時(shí)間、日期大
  • 向 TreeSet 中添加元素時(shí),只有第一個(gè)元素?zé)o須比較compareTo()方法,后面添加的所有元素都會(huì)調(diào)用compareTo()方法進(jìn)行比較。
  • 因?yàn)橹挥邢嗤?lèi)的兩個(gè)實(shí)例才會(huì)比較大小,所以向 TreeSet 中添加的應(yīng)該是同一個(gè)類(lèi)的對(duì)象
  • 對(duì)于 TreeSet 集合而言,它判斷兩個(gè)對(duì)象是否相等的唯一標(biāo)準(zhǔn)是:兩個(gè)對(duì)象通過(guò) compareTo(Object obj) 方法比較返回值
  • 當(dāng)需要把一個(gè)對(duì)象放入 TreeSet 中,重寫(xiě)該對(duì)象對(duì)應(yīng)的 equals() 方法時(shí),應(yīng)保證該方法與 compareTo(Object obj) 方法有一致的結(jié)果:如果兩個(gè)對(duì)象通過(guò) equals() 方法比較返回 true,則通過(guò) compareTo(Object obj) 方法比較應(yīng)返回 0

定制排序

  • TreeSet的自然排序是根據(jù)集合元素的大小,進(jìn)行元素升序排列。如果需要定制排序,比如降序排列,可通過(guò)Comparator接口的幫助。需要重寫(xiě)compare(T o1,T o2)方法。
  • 利用int compare(T o1,T o2)方法,比較o1和o2的大小:如果方法返回正整數(shù),則表示o1大于o2;如果返回0,表示相等;返回負(fù)整數(shù),表示o1小于o2。
  • 要實(shí)現(xiàn)定制排序,需要將實(shí)現(xiàn)Comparator接口的實(shí)例作為形參傳遞給TreeSet的構(gòu)造器。
  • 此時(shí),仍然只能向TreeSet中添加類(lèi)型相同的對(duì)象。否則發(fā)生ClassCastException異常。
  • 使用定制排序判斷兩個(gè)元素相等的標(biāo)準(zhǔn)是:通過(guò)Comparator比較兩個(gè)元素返回了0。

Set和List區(qū)別

  • Set中的元素不能重復(fù)
  • 類(lèi)似數(shù)學(xué)中集合的概念,元素是唯一的
  • 怎么叫做重復(fù)?
  • List中的元素允許重復(fù)
  • 隱含地有個(gè)順序關(guān)系
  • 支持ListIterator迭代器,能回溯

集合的能力:

并集
boolean addAll(Collection collectionToAdd)
差集
boolean removeAll(Collection collectionToAdd)
交集
boolean retainAll(Collection collectionToAdd)

代碼示例

public static void main(String[] args) {
    Set set1=new HashSet();
    set1.add(new Date());    //向列表中添加數(shù)據(jù)
    set1.add("apple");     //向列表中添加數(shù)據(jù)
    set1.add(new Integer(3));   //向列表中添加數(shù)據(jù)
    set1.add(new Socket());    //向列表中添加數(shù)據(jù)
    int size=set1.size();
    System.out.println("Set1集合的大小為:" + size);
    Set set2=new HashSet();
    set2.add("book");     //向列表中添加數(shù)據(jù)
    set2.add(new Long(3));    //向列表中添加數(shù)據(jù)
    int size2=set2.size();
    System.out.println("Set2集合的大小為:" + size2);
    set1.addAll(set2);
    System.out.println("合并后Set1集合的大小為:" + set1.size());
    set1.removeAll(set2);
    System.out.println("拆分后Set1集合的大小為: " + set1.size());
    set1.retainAll(set2);
    System.out.println("Set1和Set2集合交集的部分:" + set1.size());
}   

輸出結(jié)果:

Set1集合的大小為:4
Set2集合的大小為:2
合并后Set1集合的大小為:6
拆分后Set1集合的大小為: 4
Set1和Set2集合交集的部分:2

列表的能力:

在指定的位置插入
void add(int index, Obeject newElement)
取得某個(gè)索引的元素
Object get(int index)
設(shè)置某個(gè)索引的元素
Object set(int index, Object newElement)
刪除某個(gè)索引的元素
Object remove(int index)

代碼示例

class Persons{
    
    public String name ;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    Persons(){
        
    }
    Persons(String name){
        this.name = name;
    }
    
    public static void main(String[] args) {
        List<Persons> persons  = new ArrayList<Persons>();
        persons.add(new Persons("張三"));
        persons.add(new Persons("李四"));
        persons.add(new Persons("王五"));
        persons.add(new Persons("趙六"));
        
        System.out.println(persons.get(0).getName());//這里僅作輸出查看
        persons.set(1,new Persons("趙六"));
        persons.remove(2);
        
        for(Persons person: persons){
            System.out.println(person.getName());
        }
    }
}

輸出結(jié)果:

get方法:張三
張三
趙六
趙六

3.3.3 Map接口

  • Map與Collection并列存在。用于保存具有映射關(guān)系的數(shù)據(jù):Key-Value
  • Map 中的 key 和 value 都可以是任何引用類(lèi)型的數(shù)據(jù)
  • Map 中的 key 用Set來(lái)存放,不允許重復(fù),即同一個(gè) Map 對(duì)象所對(duì)應(yīng)的類(lèi),須重寫(xiě)hashCode()和equals()方法。
  • 常用String類(lèi)作為Map的“鍵”。
  • key 和 value 之間存在單向一對(duì)一關(guān)系,即通過(guò)指定的 key 總能找到唯一的、確定的 value。

Map體系繼承樹(shù)


3.3.3.1 Map常用方法

  • 添加、刪除操作:

  • Object put(Object key,Object value)

  • Object remove(Object key)

  • void putAll(Map t)

  • void clear()

  • 元視圖操作的方法:

  • Set keySet()

  • Collection values()

  • Set entrySet()

  • 元素查詢的操作:

  • Object get(Object key)

  • boolean containsKey(Object key)

  • boolean containsValue(Object value)

  • int size()

  • boolean isEmpty()

  • boolean equals(Object obj)

3.3.3.2 Map實(shí)現(xiàn)類(lèi)之一 HashMap

  • Map接口的常用實(shí)現(xiàn)類(lèi):HashMap、TreeMap和Properties。
  • HashMap是 Map 接口使用頻率最高的實(shí)現(xiàn)類(lèi)。
  • 允許使用null鍵和null值,與HashSet一樣,不保證映射的順序。
  • HashMap 判斷兩個(gè) key 相等的標(biāo)準(zhǔn)是:兩個(gè) key 通過(guò) equals() 方法返回 true,hashCode 值也相等。
  • HashMap 判斷兩個(gè) value相等的標(biāo)準(zhǔn)是:兩個(gè) value 通過(guò) equals() 方法返回 true。

3.3.3.3 Map實(shí)現(xiàn)類(lèi)之二 LinkedHashMap

  • LinkedHashMap 是 HashMap 的子類(lèi)
  • 與LinkedHashSet類(lèi)似,LinkedHashMap 可以維護(hù) Map 的迭代順序:迭代順序與 Key-Value 對(duì)的插入順序一致

3.3.3.4 Map實(shí)現(xiàn)類(lèi)之三 TreeMap

  • TreeMap存儲(chǔ) Key-Value 對(duì)時(shí),需要根據(jù) key-value 對(duì)進(jìn)行排序。TreeMap 可以保證所有的 Key-Value 對(duì)處于有序狀態(tài)。
  • TreeMap 的 Key 的排序:
  • 自然排序:TreeMap 的所有的 Key 必須實(shí)現(xiàn) Comparable 接口,而且所有的 Key 應(yīng)該是同一個(gè)類(lèi)的對(duì)象,否則將會(huì)拋出 ClasssCastException
  • 定制排序:創(chuàng)建 TreeMap 時(shí),傳入一個(gè) Comparator 對(duì)象,該對(duì)象負(fù)責(zé)對(duì) TreeMap 中的所有 key 進(jìn)行排序。此時(shí)不需要 Map 的 Key 實(shí)現(xiàn) Comparable 接口
  • TreeMap判斷兩個(gè)key相等的標(biāo)準(zhǔn):兩個(gè)key通過(guò)compareTo()方法或者compare()方法返回0。
  • 若使用自定義類(lèi)作為T(mén)reeMap的key,所屬類(lèi)需要重寫(xiě)equals()和hashCode()方法,且equals()方法返回true時(shí),compareTo()方法應(yīng)返回0。

案例6

package day07;

import java.util.Iterator;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

class Code implements Comparable<Code> {

    private int id;

    public Code(int id) {
        this.id = id;
    }

    public int getId() {
        return id;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }

        if (obj instanceof Code) {
            Code c = (Code) obj;

            if (c.id == this.id) {
                return true;
            }
        }
        return false;
    }

    @Override
    public int hashCode() {
        // TODO Auto-generated method stub
        return id;
    }

    @Override
    public String toString() {
        return "Code [id=" + id + "]";
    }

    @Override
    public int compareTo(Code o) {
        if (this.id > o.id) {
            return 1;
        } else if (this.id < o.id) {
            return -1;
        } else {
            return 0;
        }
    }
}

class Person1 {

    private Code id;// 身份

    private String name;// 姓名

    public Person1(String name, Code id) {
        this.name = name;
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public Code getId() {
        return id;
    }

    @Override
    public String toString() {
        return "Person1 [id=" + id + ", name=" + name + "]";
    }
}

public class Treemap {

    public static void main(String[] args) {

        // Comparable 與Comparator
        TreeMap<Code, Person1> map = new TreeMap<Code, Person1>();

        // 購(gòu)物車(chē) Map

        Person1 p1 = new Person1("張三", new Code(1111));
        Person1 p2 = new Person1("李四", new Code(1112));
        Person1 p3 = new Person1("王五", new Code(1113));
        Person1 p4 = new Person1("趙六", new Code(1114));

        Person1 p5 = new Person1("周七", new Code(1111));

        map.put(p1.getId(), p1);
        map.put(p2.getId(), p2);
        map.put(p3.getId(), p3);
        map.put(p4.getId(), p4);
        map.put(p5.getId(), p5);

        System.out.println("長(zhǎng)度" + map.size());

        Set<Entry<Code, Person1>> set = map.entrySet();

        Iterator<Entry<Code, Person1>> it = set.iterator();
        while (it.hasNext()) {
            Entry<Code, Person1> entry = it.next();

            Person1 p = entry.getValue();
            System.out.println(p.getId() + "---" + p.getName());
        }

        Person1 p = map.get(new Code(1111));
        System.out.println("xxxxxx" + p);

    }
}

輸出結(jié)果:

長(zhǎng)度4
Code [id=1111]---周七
Code [id=1112]---李四
Code [id=1113]---王五
Code [id=1114]---趙六
xxxxxxPerson1 [id=Code [id=1111], name=周七]

3.3.3.4 Map實(shí)現(xiàn)類(lèi)之四 Hashtable

  • Hashtable是個(gè)古老的 Map 實(shí)現(xiàn)類(lèi),線程安全。
  • 與HashMap不同,Hashtable 不允許使用 null 作為 key 和 value
  • 與HashMap一樣,Hashtable 也不能保證其中 Key-Value 對(duì)的順序
  • Hashtable判斷兩個(gè)key相等、兩個(gè)value相等的標(biāo)準(zhǔn),與hashMap一致。

HashMap和Hashtable的區(qū)別

一.歷史原因:Hashtable是基于陳舊的Dictionary類(lèi)的,HashMap是Java 1.2引進(jìn)的Map接口的一個(gè)實(shí)現(xiàn)

二.同步性:Hashtable是線程安全的,也就是說(shuō)是同步的,而HashMap是線程序不安全的,不是同步的

三.值:只有HashMap可以讓你將空值作為一個(gè)表的條目的key或value

3.3.3.5 Map實(shí)現(xiàn)類(lèi)之五 Properties


  • Properties 類(lèi)是 Hashtable 的子類(lèi),該對(duì)象用于處理屬性文件
  • 由于屬性文件里的 key、value 都是字符串類(lèi)型,所以 Properties 里的 key 和 value 都是字符串類(lèi)型
  • 存取數(shù)據(jù)時(shí),建議使用setProperty(String key,String value)方法和getProperty(String key)方法

代碼示例

import java.util.Iterator;
import java.util.Properties;
import java.util.Set;

public class PropertiesDemo {

    public static void main(String[] args) {
        new PropertiesDemo();
        Properties pro = new Properties();
        pro.put("name", "root");
        pro.put("pass", "root");
        pro.put("url", "jdbc:mysql://localhost:3306/db");
        String name = pro.getProperty("name");
        System.out.println(name);
        // 遍歷
        /*Set<Object> set = pro.keySet();

        Iterator<Object> it = set.iterator();

        while (it.hasNext()) {
            System.out.println(pro.get(it.next()));
        }*/
        Set<String> set = pro.stringPropertyNames();
        Iterator<String> it = set.iterator();
        while (it.hasNext()) {
            System.out.println(pro.get(it.next()));
        }
    }

}

輸出結(jié)果:

root
root
jdbc:mysql://localhost:3306/db
root

但是,常獲取數(shù)據(jù)庫(kù)密碼鏈接等是通過(guò)外部文件得到

{
    Properties pro = new Properties();
    try {
        InputStream is = getClass().getResourceAsStream("jdbc.properties");
        pro.load(is);
        System.out.println("user=="+pro.get("user"));
        System.out.println("password=="+pro.get("password"));
        System.out.println("url==="+pro.get("url"));
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

3.3.4 操縱集合的工具類(lèi) Collections

  • Collections 是一個(gè)操作 Set、List 和 Map 等集合的工具類(lèi)
  • Collections 中提供了一系列靜態(tài)的方法對(duì)集合元素進(jìn)行排序、查詢和修改等操作,還提供了對(duì)集合對(duì)象設(shè)置不可變、對(duì)集合對(duì)象實(shí)現(xiàn)同步控制等方法
  • 排序操作:(均為static方法)
  • reverse(List):反轉(zhuǎn) List 中元素的順序
  • shuffle(List):對(duì) List 集合元素進(jìn)行隨機(jī)排序
  • sort(List):根據(jù)元素的自然順序?qū)χ付?List 集合元素按升序排序
  • sort(List,Comparator):根據(jù)指定的 Comparator 產(chǎn)生的順序?qū)?List 集合元素進(jìn)行排序
  • swap(List,int, int):將指定 list 集合中的 i 處元素和 j 處元素進(jìn)行交換

查找、替換

  • Object max(Collection):根據(jù)元素的自然順序,返回給定集合中的最大元素
  • Object max(Collection,Comparator):根據(jù) Comparator 指定的順序,返回給定集合中的最大元素
  • Object min(Collection)
  • Object min(Collection,Comparator)
  • int frequency(Collection,Object):返回指定集合中指定元素的出現(xiàn)次數(shù)
  • void copy(List dest,List src):將src中的內(nèi)容復(fù)制到dest中
  • boolean replaceAll(List list,Object oldVal,Object newVal):使用新值替換 List 對(duì)象的所有舊值

同步控制

Collections 類(lèi)中提供了多個(gè) synchronizedXxx() 方法,該方法可使將指定集合包裝成線程同步的集合,從而可以解決多線程并發(fā)訪問(wèn)集合時(shí)的線程安全問(wèn)題


3.3.4.1 Collection和Collections區(qū)別

Collections是個(gè)java.util下的類(lèi),它包含有各種有關(guān)集合操作的靜態(tài)方法。

Collection是個(gè)java.util下的接口,它是各種集合結(jié)構(gòu)的父接口。

3.3.5 Enumeration

Enumeration 接口是 Iterator 迭代器的 “古老版本”


案例7

Enumeration stringEnum = new StringTokenizer("a-b*c-d-e-g", "-");
while(stringEnum.hasMoreElements()){
    Object obj = stringEnum.nextElement();
    System.out.println(obj); 
}

輸出結(jié)果:

a
b*c
d
e
g
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • Collection ├List │├LinkedList │├ArrayList │└Vector │└Stac...
    AndyZX閱讀 893評(píng)論 0 1
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法,類(lèi)相關(guān)的語(yǔ)法,內(nèi)部類(lèi)的語(yǔ)法,繼承相關(guān)的語(yǔ)法,異常的語(yǔ)法,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,765評(píng)論 18 399
  • java筆記第一天 == 和 equals ==比較的比較的是兩個(gè)變量的值是否相等,對(duì)于引用型變量表示的是兩個(gè)變量...
    jmychou閱讀 1,518評(píng)論 0 3
  • 集合類(lèi)簡(jiǎn)介 為什么出現(xiàn)集合類(lèi)?面向?qū)ο笳Z(yǔ)言對(duì)事物的體現(xiàn)都是以對(duì)象的形式,所以為了方便對(duì)多個(gè)對(duì)象的操作,就要對(duì)對(duì)象進(jìn)...
    阿敏其人閱讀 1,442評(píng)論 0 7
  • 上高中時(shí)和同學(xué)說(shuō),我要玩到29歲,然后結(jié)婚。同班的一個(gè)男生說(shuō),到時(shí)候誰(shuí)來(lái)收拾這場(chǎng)殘局呀。氣得我追打他整個(gè)教室。 現(xiàn)...
    春霖桃語(yǔ)閱讀 219評(píng)論 0 0