jav核心(十四):集合類型操作:Collection、List、Set;Map集合;Iterator迭代器


一、java.util.List
1、List總結
  • List中允許保存重復的數據;
  • List中允許保存多個null;
  • 常用實現類:ArrayList【推薦使用】、Vector、LinkedList;
  • List中數據是有序的,按照數據添加順序進行排序;
  • 由於List是有序的,因此List新增加了一個方法:E get(int index) ,【Collection、Set接口均沒有get(int index)方法】。
 
2、ArrayList和Vector的區別
  (1)ArrayList和Vector,都是List接口的實現類。
NO 區別點 ArrayList Vector
1 推出時間 JDK1.2,屬於新增類 JDK1.0,屬於舊類
2 性能 異步處理
同步處理
方法采用synchronized修飾,為同步方法
3 安全 非線程安全 線程安全
4 數據輸出方式 Iterator、ListIterator、foreach
Iterator、ListIterator、foreach、
Enumeration
 

  (2)ArrayList和Vector都是用數組實現的,主要有以下幾個區別:

  • Vector是多線程安全的,線程安全就是說多線程訪問同一代碼,不會產生不確定的結果。而ArrayList不是,這個可以從源碼中看出,Vector類中的方法很多有synchronized進行修飾,這樣就導致了Vector在效率上無法與ArrayList相比;
  • 兩個都是采用的線性連續空間存儲元素,但是當空間不足的時候,兩個類的增加方式是不同。
  • Vector可以設置增長因子,而ArrayList不可以。
  • Vector是一種老的動態數組,是線程同步的,效率很低,一般不贊成使用。

   (3)適用場景分析:

  • Vector是線程同步的,所以它也是線程安全的,而ArrayList是線程異步的,是不安全的。如果不考慮到線程的安全因素,一般用ArrayList效率比較高。
  • 如果集合中的元素的數目大於目前集合數組的長度時,在集合中使用數據量比較大的數據,用Vector有一定的優勢。

 

3、Vertor向量類型數據輸出:Vertor --> Iterator | Enumeration
  Java.util.Vertor是JDK1.0中設計的向量類型。后來在JDK1.2中新增了Collection、List、Set接口,為保持集合統一型,修改Vertor類的定義,使其實現了List接口。 與新集合的實現不同,Vertor是同步的。
  Java.util.Enumeration是JDK1.0中定義的接口,和Java.util.Iterator(JDK1.2出現)迭代器功能類似。其中Enumeration接口包含兩個方法:
  • hasMoreElements():測試此枚舉是否包含更多的元素。
  • nextElement():如果此枚舉對象至少還有一個可提供的元素,則返回此枚舉的下一個元素。
public class Test {
    public static void main(String[] args) {
        List<String> vertor = new Vector<String>();
        vertor.add("A");
        vertor.add("B");
        vertor.add("C");
        //輸出數據:使用迭代器Iterator
        Iterator<String> iterator = vertor.iterator();
        while (iterator.hasNext()){
            String data = iterator.next();
            System.out.println(data);
        }
 
        System.out.println("*******");
        //輸出數據:使用Enumeration
        Enumeration<String> enumeration = ((Vector<String>) vertor).elements();
        while (enumeration.hasMoreElements()){
            String data = enumeration.nextElement();
            System.out.println(data);
        }
    }
}
//程序運行結果:
A
B
C
*******
A
B
C

 

二、Java.util.Set
1、Set總結
  API描述: 一個不包含重復元素的 collection。更正式地說,set 不包含滿足 e1.equals(e2) 的元素對 e1 和 e2,並且最多包含一個 null 元素。正如其名稱所暗示的,此接口模仿了數學上的 set 抽象。
  • Set不允許保存重復的數據【不同實現類,對重復數據的評定標准不一樣】;
  • 常用實現類:HashSet、TreeSet;
  • HashSet允許保存一個null,TreeSet不允許保存null;
  • HashSet中的數據是無序的;
  • TreeSet中的數據是有序的,數據按照升序排列【通過調用數據元素的compareTo()方法進行排序,因此數據元素需要實現Comparable接口,否則會拋出ClassCastException異常】。
 
2、HashSet中,數據重復的評定標准:
   當且僅當( e1.hashCode() == e2.hashCode() )  && e1.equals(e2) 為true時,才認定e1和e2重復。
  
  (1)數據重復測試一: e1.equals(e2)為true時,hashCode()值必然相同的情況
/**
 * 按照規范重寫Book類的equals()方法、hashCode()方法
 */
class Book {
    private int price;
    private String name;
    public Book(int price, String name) {
        this.price = price;
        this.name = name;
    }
 
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Book book = (Book) o;
        return price == book.price &&
                Objects.equals(name, book.name);
    }
 
    @Override
    public int hashCode() {
        return Objects.hash(price, name);
    }
 
    @Override
    public String toString() {
        return this.name + "--" + this.price;
    }
}
 
 
public class Test {
    public static void main(String[] args) {
        Book book = new Book(100, "java開發");
        Book book1 = new Book(100, "java開發");
        Book book2 = new Book(100, "設計模式");
        Book book3 = new Book(10, "abc");
 
        System.out.println("*********");
        System.out.println(book.hashCode());     //-1166307760
        System.out.println(book1.hashCode());    //-1166307760
        System.out.println(book2.hashCode());    //1100964814
        System.out.println(book.equals(book1));    //true
        System.out.println(book.equals(book2));    //false
        System.out.println("*********");
 
        Set<Book> hashSet = new HashSet<>();
        hashSet.add(book);
        hashSet.add(book1);     //book1 與 book 重復,不進行保存
        hashSet.add(book2);     //book2 不重復
        hashSet.add(book3);     //book3 不重復
        System.out.println(hashSet);
    }
}
//程序執行結果:
*********
-1166307760
-1166307760
1100964814
true
false
*********
[設計模式--100, abc--10, java開發--100]

 

  (2)數據重復測試二:e1.equals(e2)為true,但hashCode()值不同的情況

class Book {
    private int price;
    private String name;
    public Book(int price, String name) {
        this.price = price;
        this.name = name;
    }
    @Override
    public String toString() {
        return this.name + "--" + this.price;
    }
 
 
    //任何對象之間比較,均返回true
    public boolean equals(Object o) {
        return true;
    }
 
    //使用隨機數生成hashCode
    public int hashCode() {
        return Objects.hash(Math.random());
    }
}
 
 
public class Test {
    public static void main(String[] args) {
        Book book = new Book(100, "java開發");
        Book book1 = new Book(100, "java開發");
        Book book2 = new Book(100, "設計模式");
 
 
        System.out.println("*********");
        System.out.println(book.hashCode());
        System.out.println(book1.hashCode());
        System.out.println(book2.hashCode());
        System.out.println(book.equals(book1));
        System.out.println(book.equals(book2));
        System.out.println("*********");
 
 
        Set<Book> hashSet = new HashSet<>();
        hashSet.add(book);
        hashSet.add(book1);     //book1 與 book 重復
        hashSet.add(book2);     //book2 不重復
        System.out.println(hashSet);
    }
}
//程序執行結果
*********
920603493
-1541131927
1273275611
true
true
*********
[java開發--100, 設計模式--100, java開發--100]

 

 3、TreeSet中,數據重復的評定標准:
  TreeSet<T>中的元素T必須實現java.lang.Comparable接口,重寫接口定義的 public int  compareTo( T o) 方法。
   當且僅當 e1.compareTo(e2) 返回結果為0時,認為e1、e2重復。
  TreeSet不使用equals()、hashCode()方法進行判定。
class Book implements Comparable{
    private int price;
    private String name;
    public Book(int price, String name) {
        this.price = price;
        this.name = name;
    }
    @Override
    public String toString() {
        return this.name + "--" + this.price;
    }
 
 
    @Override
    public boolean equals(Object o) {
        return true;
    }
 
 
    @Override
    public int hashCode() {
        return Objects.hash("1111");
    }
 
 
    @Override
    public int compareTo(Object o) {
        return 1;
    }
}
 
 
public class Test {
    public static void main(String[] args) {
        Book book = new Book(100, "java開發");
        Book book1 = new Book(100, "java開發");
        Book book2 = new Book(100, "設計模式");
 
        System.out.println("*********");
 
        Set<Book> hashSet = new TreeSet<>();
        hashSet.add(book);
        hashSet.add(book1);     
        hashSet.add(book2);     
        System.out.println(hashSet);
    }
}
//程序執行結果
*********
[java開發--100, java開發--100, 設計模式--100]

 

4、說明:一般情況下,比較兩個對象是否相同,通過hashCode()和equals()方法判斷
  • 首先判斷hashCode()值是否相等,如果不相等,則認為e1、e2不相同;如果相等,則繼續判斷e1.equals(e2)是否為true,若為true則認為e1、e2相同,否則認為e1、e2不相同;
  • Comparable的compareTo()方法只是作為對象的排序使用,但並不能真正區分兩個對象是否相同。
 
三、Java.util.Map
1、Map總結
  • 將鍵映射到值的對象。一個映射不能包含重復的鍵;每個鍵最多只能映射一個值。
//語法定義
public
interface Map<K,V>
 
2、Map接口中的方法
NO 方法名稱
1
public V  put( K key,  V value) 
          將指定的值與此映射中的指定鍵相關聯(可選操作)。
2
public V  get( Object key) 
          返回此映射中映射到指定鍵的值。
3
public  Set< Map.Entry< K, V>>   entrySet()
          返回此映射中包含的映射關系的 set 視圖。
4
public Set<K>  keySet() 
          返回此映射中包含的鍵的 set 視圖。
 
 
3、HashMap和HashTable的區別
  HashMap是JDK1.2中用來代替HashTable的類,也就是說建議使用HashMap,不要使用HashTable。
NO 區別點 HashMap HashTable
1 推出時間 JDK1.2,屬於新增類 JDK1.0,屬於舊類
2 性能 異步處理
同步處理
方法采用synchronized修飾
3 安全 非線程安全 線程安全
4 是否允許null 允許key或value為null key和value均不能為null

 
  
    (1)基本功能上的區別:
  • 同步性: HashTable的方法是同步的,HashMap是不同步的。所以在多線程場合要手動同步HashMap。
  • 對Null的支持: HashTable不允許null值(key和value都不可以),HashMap允許null值(key和value都可以,只容許有一個null值的key,可以有多個null值的value)。
  • 數據輸出方式:HashTable可以使用Enumeration和Iterator,HashMap只可以使用Iterator。
    (2)底層存儲數據的區別
  • HashTable中hash數組默認大小是11,增加的方式是 old*2+1。HashMap中hash數組的默認大小是16,而且一定是2的指數。
  • 哈希值的使用不同,HashTable直接使用對象的hashCode。而HashMap重新計算hash值,而且用與代替求模。
//HashTable : 計算哈希值
int hash = key.hashCode();
int index = (hash & 0x7FFFFFFF) % tab.length;
//HashMap : 計算哈希值
int hash = hash(k);
int i = indexFor(hash, table.length);
 
//HashMap通過key,重新計算hash值
static int hash(Object x) {
    int h = x.hashCode();
    h += ~(h << 9);
    h ^= (h >>> 14);
    h += (h << 4);
    h ^= (h >>> 10);
    return h;
}
 
//HashMap使用新計算出的hash值進行求模
static int indexFor(int h, int length) {
    return h & (length - 1);
}

 

4、將Map中的數據,通過迭代器輸出:Map —> Set  —> Iterator
  • 調用Map.entrySet()方法,將Map集合轉換為Set集合,其中Set中的泛型為:Map.Entry<K,V>;
  • 調用Set.iterator()方法,將Set集合轉換為Iterator迭代器,泛型依然是:Map.Entry<K,V>;
  • 調用Iterator的hasNext()、next()方法,循環取出Map.Entry<K,V>接口對象;
  • 調用Map.Entry接口的getKey()獲取key、getValue()獲取value。

class Book {
    private int price;
    private String name;
    public Book(int price, String name) {
        this.price = price;
        this.name = name;
    }
    @Override
    public String toString() {
        return this.name + "--" + this.price;
    }
}
 
 
public class Test {
    public static void main(String[] args) {
        Book book = new Book(100, "java開發");
        Book book1 = new Book(100, "java開發");
        Book book2 = new Book(56, "設計模式");
 
        System.out.println("*********");
        Map<String,Book> map = new HashMap<>();
        map.put("book",book);
        map.put("book1",book1);
        map.put("book2",book2);
 
        //將Map中的數據,通過迭代器輸出:Map —> Set  —> Iterator
        Set<Map.Entry<String,Book>> set = map.entrySet();
        Iterator<Map.Entry<String,Book>> iterator = set.iterator();
        while (iterator.hasNext()){
            Map.Entry<String,Book> entry = iterator.next();
            String key = entry.getKey();
            Book value = entry.getValue();
            System.out.println(key+" : "+value); }
    }
}
//程序執行結果
*********
book2 : 設計模式—56
book1 : java開發--100
book : java開發--100

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM