1. 程式人生 > >三大集合特點

三大集合特點

一、Set集合,其主要實現類有HashSet、TreeSet。存放物件的引用,不允許有重複物件。
通過java的equals()方法判別。如果有特殊需求須過載equals()方法。
1、HashSet(),呼叫物件的hashCode()方法,獲得雜湊碼,然後再集合中計算存放物件的位置。通過比較雜湊碼與equals()方法來判別是否重複。所以,過載了equals()方法同時也要過載hashCode()方法。
2、TreeSet(),繼承ShortedSet介面,能夠對集合中物件排序。預設排序方式是自然排序,但該方式只能對實現了Comparable介面的物件排序,java中對Integer、Byte、Double、Character、String等數值型和字元型物件都實現了該介面。
如果有特殊排序,須過載該介面下的compareTo()方法或通過Comparator介面的實現類構造集合。
二、List集合,其主要實現類有LinkedList、ArrayList,前者實現了連結串列結構,後者可代表大小可變的陣列。List的特點是能夠以線性方式儲蓄物件,並允許存放重複物件。List能夠利用Collections類的靜態方法sort排序。sort(List list)自然排序;sort(List listm,Comparator comparator)客戶化排序。
三、Map集合,其主要實現類有HashMap、TreeMap。Map對值沒有唯一性要求,對健要求唯一,如果加入已有的健,原有的值物件將被覆蓋。HashMap類按照雜湊演算法來存取鍵物件,可以過載equals()、hashCode()方法來比較鍵,但是兩者必須一致。TreeMap,可自然排序,也可通過傳遞Comparator的實現類構造TreeMap。
(1)集合的由來?
我們學習的是Java – 面向物件 – 操作很多物件 – 儲存 – 容器(陣列和StringBuffer) – 陣列
而陣列的長度固定,所以不適合做變化的需求,Java就提供了集合供我們使用。
(2)集合和陣列的區別?
A:長度區別
陣列固定
集合可變
B:內容區別
陣列可以是基本型別,也可以是引用型別
集合只能是引用型別
C:元素內容
陣列只能儲存同一種類型
集合可以儲存不同型別(其實集合一般儲存的也是同一種類型)
(3)集合的繼承體系結構?
由於需求不同,Java就提供了不同的集合類。這多個集合類的資料結構不同,但是它們都是要提供儲存和遍歷功能的,
我們把它們的共性不斷的向上提取,最終就形成了集合的繼承體系結構圖。

Collection:
|–List 有序(元素存入集合的順序和取出的順序一致),元素都有索引,而且元素可以重複。
|–ArrayList
|–Vector
|–LinkedList
|–Set 無序(存入和取出順序有可能不一致),不可以儲存重複元素。必須保證元素唯一性。
|–HashSet
|–TreeSet
Collection的功能:
A:新增功能
boolean add(Object obj):向集合中新增一個元素
boolean addAll(Collection c):向集合中新增一個集合的元素
B:刪除功能
void clear():刪除集合中的所有元素
boolean remove(Object obj):向集合中刪除指定的元素
booleanremoveAll(Collection c):向集合中刪除一個指定的集合元素
C:判斷功能
boolean isEmpty():判斷集合是否為空
boolean contains(Object obj):判斷集合中是否存在指定的元素
boolean containsAll(Collection c):判斷集合中是否存在指定的元素
D:遍歷功能
Iterator iterator():就是用來獲取集合中每一個元素
E:長度功能
int size():獲取集合中的元素個數
F:交集功能
boolean retainAll(Collection c):判斷兩個集合中是否有相同的元素
G:轉換功能
Object[] toArray():把集合變成陣列
小練習:遍歷集合中的元素,判斷是否存在元素“hello”。

/*
 * 請遍歷集合:也就是獲取到集合中的每一個元素。
 * 判斷集合中是否存在"hello"這個元素.
 * 注意:
 *      在往集合中新增元素的時候,集合預設接收的是Object型別。
 *      也就是說你開始儲存字串的時候,其實做了一個向上轉型的操作。
 * 
 *      在獲取元素的時候,預設還是以Object型別的返回。
 *      但是,你明明知道這應該是String型別。
 *      所以,如果你想使用String型別的特殊功能,就必須做向下轉型。
 *      如果僅僅是為了看結果,就不用。因為通過多型的形式,最終輸出語句呼叫的是String類的toString()
 */
public class CollectionDemo2 { public static void main(String[] args) { flag=true; //元素標記符, Collection c = new ArrayList(); //建立集合物件 // 新增元素 c.add("hello"); // String -- Object c.add("world"); c.add("java"); // 直接使用判斷功能 // System.out.println("contains:"+c.contains("hello")); // System.out.println("c:" + c);//若存在,則會輸出true // 遍歷集合,獲取到每一個元素,然後判斷這個元素是否是hello // Object[] toArray():把集合變成陣列。 Object[] objs = c.toArray(); for (int x = 0; x < objs.length; x++) { //將Object型別的陣列強制轉換為String型別 String s = (String) objs[x]; if(s.equals("hello")){ flag=true; //如果存在,就輸出真,否則輸出假 }else{ flag=false; } System.out.println(s + "***" + s.length()+"***"+flag); } } }

小練習:用迭代器遍歷集合中的元素。

/*
 * 成員方法:
 *      Object next():獲取元素,並自動移動到下一個位置等待獲取。
 *      boolean hasNext():判斷迭代器中是否還有元素。 
 * NoSuchElementException:沒有這樣的元素異常。你已經獲取到元素末尾了,你還要獲取,已經沒有元素了。所以報錯了。
 */
public class IteratorDemo {
    public static void main(String[] args) {
        // 建立物件
        Collection c = new ArrayList();

        // 新增元素
        c.add("hello");
        c.add("world");
        c.add("java");

        // 方式1
        // Object[] objs = c.toArray();
        // for (int x = 0; x < objs.length; x++) {
        // String s = (String) objs[x];
        // System.out.println(s);
        // }// 方式2  
    // Iterator iterator():就是用來獲取集合中每一個元素。
        // 通過集合物件獲取迭代器物件
        Iterator it = c.iterator();// 這是返回的是Iterator的子類物件,多型

        while (it.hasNext()) {
            // System.out.println(it.next());
            String s = (String) it.next();
            System.out.println(s);
        }   }  }

list介面

 List本身是Collection介面的子介面,具備Collection的所有方法。現在學習list體系特有的共性方法,查閱方法發現List的特有方法都有索引,這是該集合最大的特點。

1)List特有功能:
A:新增功能
void add(int index,Object obj):在指定位置新增元素
B:刪除功能
Object remove(int index):根據指定索引刪除元素,並把刪除的元素返回
C:修改功能
Object set(int index,Object obj):把指定索引位置的元素修改為指定的值,返回修改前的值。
D:獲取功能
Object get(int index):返回指定元素在集合中第一次出現的索引
int indexOf(Object obj):獲取指定位置的元素,如果該元素不存在返回-1;所以,通過-1,可以判斷一個元素是否存在 int lastIndexOf(Object obj):反向索引指定元素的位置
List subList(start,end):獲取子列表
ListIterator listIterator():列表迭代器(List集合特有的迭代器)
2)List的遍歷方式
A:Iterator 迭代器
B:ListIterator迭代器(瞭解)
C:普通for(和list的get方法使用)
3)ListIterator迭代器
A:是Iterator的子介面。
B:有自己的特有功能,可以逆向遍歷資料,但是需要先正向遍歷。一般不用。

/*
 * ListIterator listIterator():列表迭代器
 * 
 * boolean hasNext()
 * Object next()
 * 
 * 特有功能:
 * boolean hasPrevious()        
 * Object previous() 
 * 
 * 雖然,可以逆向遍歷,但是,要求先正向遍歷,然後才能逆向遍歷。
 */
public class ListDemo5 {
    public static void main(String[] args) {
        // 建立集合物件
        List list = new ArrayList();

        // 新增元素
        list.add("hello");
        list.add("world");
        list.add("java");

        // 遍歷
        ListIterator lit = list.listIterator();
        while (lit.hasNext()) {
            String s = (String) lit.next();
            System.out.println(s);
        }

        System.out.println("----------------");
        // System.out.println(lit.previous());
        // System.out.println(lit.previous());
        // System.out.println(lit.previous());
        // // NoSuchElementException
        // System.out.println(lit.previous());
        // 逆向遍歷
        while (lit.hasPrevious()) {
            String s = (String) lit.previous();
            System.out.println(s);
        }
    }
}

4)面試題:併發修改異常
A:併發修改異常的產生原因:用迭代器遍歷集合,用集合去操作集合。
B:解決方案:a:使用集合操作。
b:使用列表迭代器操作。
程式碼如下:

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
/*
 * ListIterator listIterator():列表迭代器
 * 
 * public interface ListIterator extends Iterator
 * 
 * 面試題:ConcurrentModificationException:併發修改異常。
 *      這是個什麼異常,怎麼產生的,怎麼解決的? 
 * 怎麼產生:
 *      當我們通過迭代器迭代元素的過程中,又通過集合去添加了元素。這種情況是不允許的。
 *      因為迭代器是依賴於集合存在的,如果集合發生改變,迭代器也應該相應的發生改變。
 *      而我們目前看到的確實,迭代器沒變,集合變了。所以,報出了一個併發修改異常。
 * 
 * 注意問題:通過迭代器遍歷集合的時候,是不能通過集合去操作(新增,刪除)。
 * 那麼,我們可不可以這樣理解呢?
 * A:全部通過迭代器操作:元素是新增到剛遍歷的那個元素後面。
 *      通過迭代器迭代的時候,可以通過迭代器對集合進行操作。
 * B:全部通過集合操作:元素是新增到最後的。
 *      通過集合普通for遍歷的時候,可以通過集合去操作。
 */
public class ListDemo4 {
    public static void main(String[] args) {
        // 建立集合物件
        List list = new ArrayList();

        // 新增元素
        list.add("hello");
        list.add("world");
        list.add("java");

        // 迭代器
        // Iterator it = list.iterator();
        // while (it.hasNext()) {
        // String s = (String) it.next();
        // System.out.println(s);
        // }
        // System.out.println("-----------");

        // 需求:請遍歷集合,判斷其中是否有"hello"這個元素,如果有,就再新增一個元素:"IOS"
        // Iterator it = list.iterator();
        // while (it.hasNext()) {
        // String s = (String) it.next();
        // if ("hello".equals(s)) {
        // list.add("IOS");
        // // it = list.iterator();//這樣從原理是可以解決的,但是它會引起另外一個問題。
        // }
        // }
        // System.out.println("list:" + list);
        // System.out.println("-----------");

        // 完全通過集合實現
        // for (int x = 0; x < list.size(); x++) {
        // String s = (String) list.get(x);
        // if ("hello".equals(s)) {
        // list.add("IOS");
        // }
        // }
        // System.out.println("list:"+list);
        // System.out.println("-----------");

        // 遍歷
        ListIterator lit = list.listIterator();
        while (lit.hasNext()) {
            String s = (String) lit.next();
            if ("hello".equals(s)) {
                lit.add("IOS");
            }
        }
        System.out.println("list:" + list);
    }
}

5)List:
|–ArrayList:底層資料結構是陣列,執行緒不安全(即不同步),它的出現替代了Vector,增刪的效率很慢,但是查詢的效率很高。
|–Vector:底層資料結構是陣列,執行緒安全,無論增刪還是查詢都非常慢。
|–LinkedList:底層是連結串列,執行緒不安全,對元素的增刪的操作效率很高,查詢效率低。

ArrayList的小練習:
需求:我現在用ArrayList儲存多個字串元素。
比如說資料如下:hello,world,java,hello,.net,java,php,IOS,java,android
我要求你寫程式,實現去除重複元素。也就是說結果是:hello,world,java,.net,php,IOS,android

 5)List:
   |--ArrayList:底層資料結構是陣列,執行緒不安全(即不同步),它的出現替代了Vector,增刪的效率很慢,但是查詢的效率很高。
   |--Vector:底層資料結構是陣列,執行緒安全,無論增刪還是查詢都非常慢。
   |--LinkedList:底層是連結串列,執行緒不安全,對元素的增刪的操作效率很高,查詢效率低。

ArrayList的小練習:
需求:我現在用ArrayList儲存多個字串元素。 
  比如說資料如下:hello,world,java,hello,.net,java,php,IOS,java,android
 我要求你寫程式,實現去除重複元素。也就是說結果是:hello,world,java,.net,php,IOS,android

方法二:

  /*
 * 在同一個集合上操作:雙層迴圈實現
 *      第一方式沒有問題,第二種可能有問題。
 *      但是,第二種的問題也是可以解決的?
 *      怎麼解決呢?
 *      把每次刪除掉元素的那個位置,在回來比較一次即可。
 */
public class ArrayListTest2 {
    public static void main(String[] args) {
        // 建立舊集合,並新增元素
        ArrayList array = new ArrayList();

        array.add("hello");
        array.add("world");
        array.add("java");
        array.add("hello");
        array.add(".net");
        array.add("java");
        array.add("java");
        array.add("java");
        array.add("php");
        array.add("IOS");
        array.add("java");
        array.add("android");

        // 這下面的程式碼和選擇排序類似。理解即可。最好通過斷點看過程。
        for (int x = 0; x < array.size() - 1; x++) {
            for (int y = x + 1; y < array.size(); y++) {
                if (array.get(y).equals(array.get(x))) {
                    array.remove(y);
                    y--;
                }
            }
        }

        // 遍歷
        Iterator it = array.iterator();
        while (it.hasNext()) {
            String s = (String) it.next();
            System.out.println(s);
        }
    }
}

下面是一個面試題:用ArrayList儲存學生,如何去除重複的元素?

“`
import java.util.ArrayList;
import java.util.Iterator;

/*
* ArrayList如果儲存的是學生,那麼,怎麼去除重複元素呢?
* 問題:如何知道學生是重複的。
* 需求:如果學生的姓名和年齡相同,我就認為是同一個學生。即重複值。
*
* 通過簡單分析,我們估計是判斷那裡出問題了。
* 怎麼辦呢?
* 看判斷的方法。
* 而我們又知道,判斷的方法是API提供的。不是自己的寫的。
* 看原始碼,看底層到底怎麼實現的。
* 通過看原始碼,我們發現,底層依賴的是equals()。
* 由於學生類中,我們並沒有equals()方法,所以,預設用的是Object的方法。
* 而Object類的方法,預設比較的是地址值。
* 由於學生物件都是new出來的,地址值肯定不一樣,所以從這個角度考慮結論是正確的。
* 但是不符合我們的需求。
* 腫麼辦?
* 重寫equals(),讓他按照我們的需要來比較。
*/

//標準學生類
public class Student {
//定義兩個成員變數
private String name;
private int age;

public Student() {
}

public Student(String name, int age) {
    this.name = name;
    this.age = age;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public int getAge() {
    return age;
}

public void setAge(int age) {
    this.age = age;
}

   //重寫equals方法
@Override
public boolean equals(Object obj) {
    // 提高效率
    if (this == obj) {
        return true;
    }

    // 提高健壯性
    if (!(obj instanceof Student)) {
        return false;
    }

    // 向下轉換
    Student s = (Student) obj;
    return this.name.equals(s.name) && this.age == s.age;
}

}

public class ArrayListTest3 {
public static void main(String[] args) {
ArrayList array = new ArrayList();

    Student s1 = new Student("301宿舍--笨笨", 22);
    Student s2 = new Student("301宿舍--姍姍", 23);
    Student s3 = new Student("301宿舍--姍姍", 30);
    Student s4 = new Student("301宿舍--紅紅", 20);
    Student s5 = new Student("301宿舍--紅紅", 20);
    Student s6 = new Student("301宿舍--蛋蛋", 24);
            Student s7 = new Student("301宿舍--媛媛", 22);
            Student s8 = new Student("301宿舍--歪歪", 23);

    array.add(s1);
    array.add(s2);
    array.add(s3);
    array.add(s4);
    array.add(s5);
    array.add(s6);

    // 建立新集合
    ArrayList array2 = new ArrayList();

    // 遍歷舊集合,獲取到每一個元素
    Iterator it = array.iterator();
    while (it.hasNext()) {
        Student s = (Student) it.next();
        // 在新集合中判斷,看是否存在這個元素
        if (!array2.contains(s)) {
            // 如果s不再array2中存在,就新增
            array2.add(s);
        }
    }

    // array2就是沒有重複元素的集合。
    // 遍歷array2
    for (int x = 0; x < array2.size(); x++) {
        Student s = (Student) array2.get(x);
        System.out.println(s.getName() + "***" + s.getAge());
    }
}

}

“`這裡寫圖片描述