集合框架-----Collection和Map

集合框架—–Collection和Map

記錄一下學習的集合框架,梳理思路,也便於以後的查看。如果有錯誤之處,還望大家不吝指出,多謝哈。

集合框架之Collection

來張Collection體系圖:

這裏寫圖片描述

  • Collection概述:

    • Collection是最基本的集合接口,一個Collection代表一組Object,即Collection的元素(Elements)。一些Collection允許相同的元素而另一些不行。一些能排序而另一些不行。Java SDK不提供直接繼承自Collection的類,Java SDK提供的類都是繼承自Collection的“子接口”如List和Set。

    • 所有實現Collection接口的類都必須提供兩個標準的構造函數:無參數的構造函數用於創建一個空的Collection,有一個Collection參數的構造函數用於創建一個新的Collection,這個新的Collection與傳入的Collection有相同的元素。後一個構造函數允許用戶複製一個Collection。

  • List

    • 集合中存取的元素有序(存和取的順序一致),有索引,可以存儲重複值。
  • Set

    • 集合中存取的元素無序(存和取的順序不一致),無索引,不可以存儲重複的值。

    注意:因爲List和Set都是Collection的子接口,如果想使用接口,就必須使用它的實現類。如: List list = new Arraylist();

  • Collection集合遍歷

    • 1,將集合轉換成數組,(利用toArray()方法 )再使用for循環遍歷即可。
    • 2,迭代器遍歷(使用集合中iterator()方法獲得Iterator對象)

      • 僞代碼如下:
        Iterator it = list.iterator();  //獲取Iterator 對象
        while(it.hasNext()) {   //判斷集合中是否還有元素
            it.next();             //得到元素值
        }
    • 3,增強for循環遍歷

      • 僞代碼如下
      Collection c = new ArrayList();
      //Object obj = new Student("張三",23);
      c.add(new Student("張三",23));    //Object obj = new Student("張三",23); 這裏會自動類型提升爲Object
      c.add(new Student("李四",24));
      c.add(new Student("王五",25));
      c.add(new Student("馬六",26));
      for (Object value : c) {
      System.out.println(value);
      }
  • List集合特有的遍歷

    • 1,根據List集合的特點:有索引,可以通過 list.get(int index);方法遍歷
    • 2,List特有的方法:ListIterator。根據listIterator()方法獲得ListIterator迭代器對象。
  • 集合遍歷注意事項

    • 當使用Iterator迭代器遍歷集合需要增添或修改元素時,很可能會發生併發修改異常(ConcurrentModificationException)。
      • 原因:當遍歷集合時,增添或修改集合中元素,使用的是集合的方法,而迭代器並不知道,這就導致出現了併發修改異常。
      • 解決辦法:
        • 1,使用普通for循環(通過索引刪除,一個集合的最大索引爲:list.size() - 1; 注意:索引要字減一)list.remove(index–);
        • 2,使用ListIterator迭代器,因爲此迭代器中特有添加和刪除的方法。
  • List集合中三個子類的特點

    • ArrayList:底層數據結構是數組,查詢修改快,增刪慢,線程不安全,但效率高。
    • Vector:底層數據結構是數組,查詢修改增刪都慢,線程安全,但效率低。
    • LinkedList:底層數據結構是鏈表,查詢修改慢,增刪快,線程不安全,但效率高。
    • 結論
      • 查詢多用ArrayList
      • 增山多用LinkedList
      • 都多用Arraylist
  • 泛型

    • 如:Collection<String> c = new Arraylist<>();定義了一個泛型爲String類型的集合。
    • 使用泛型的好處:
      • 提高安全性(將運行期的錯誤轉換到編譯期)
      • 省去強轉的麻煩
    • 注意:
      • <>中放的必須是引用數據類型。
      • 前後的泛型必須一致,或者後面的泛型可以省略不寫(JDK1.7新特性,菱形泛型)
      • 泛型最好不要定義成Object,沒有意義。
  • HashSet集合類(Set集合的實現類)
    • 特點:
      • 方法和Collection中方法一樣
      • 當向Set集合中存儲重複元素時,返回值爲false
      • HashSet的繼承體系中有重寫toString方法
    • HashSet存儲自定義對象:
      • 爲了保證元素的唯一性,自定義對象的類中必須重寫hashCode()和equals()方法。
        • 當哈希值一樣時,纔會調用equals()方法。
  • LinkedHashSet集合類(HashSet的子類)
    • 特點:
      • 底層是鏈表實現的,是Set集合中唯一保證怎麼存就怎麼取。
      • 該類是HashSet的子類,所以也是保證元素唯一的,與HashSet的原理一樣。
  • TreeSet集合類(Set集合的實現類)
    • 特點:
      • 保證元素的唯一性
      • 可以對元素進行排序
    • 排序的方式(自定義對象時)
      • 自然排序:自定義對象的類需要實現Compareable接口,並重寫接口中compareTo()方法。
        • 在TreeSet集合類中如何存儲元素取決於compareTo()方法的返回值:
          • 返回值爲0:集合中只會存儲一個元素。
          • 返回值爲正數:集合怎麼存,就會怎麼輸出。
          • 返回值爲負數:集合會將存儲的元素倒序輸出。
        • 來個自然排序的代碼:
//自定義對象,Person類
public class Person implements Comparable<Person>{
    private String name;
    private int age;
    public Person() {
        super();

    }
    public Person(String name, int age) {
        super();
        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;
    }
    @Override
    //按照年齡排序
    public int compareTo(Person p) {
        //排序:如果是新的(後進來的)減去老的(先進來的),是從小到大排序。
        //       如果是老的減去新的,就是從大到小排序
        //      this代表新的,p代表老的
        int num = this.age - p.age;     //判斷年齡是否相同
        //當年齡相同是,比較姓名是否相同。
        int num2 = num == 0 ? this.name.compareTo(p.name) : num;
        return num2;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }   
}


//測試類
import java.util.TreeSet;

public class TreeSetTest {
    /**
     * 演示
     *  按年齡的大小排序(按年齡從小到大排序)
     * TreeSet存儲自定義對象並遍歷(按年齡從小到大排序)
     */
    public static void main(String[] args) {
        TreeSet<Person> ts = new TreeSet<>();

        ts.add(new Person("zhangsan", 23));
        ts.add(new Person("lisi", 16));
        ts.add(new Person("wangwu", 24));
        ts.add(new Person("zhaoliu", 34));
        ts.add(new Person("aaaa", 44));

        System.out.println(ts);
    }
}
//輸出結果:
/*  
[Person [name=lisi, age=16], 
Person [name=zhangsan, age=23], 
Person [name=wangwu, age=24], 
Person [name=zhaoliu, age=34], 
Person [name=aaaa, age=44]]
*/
比較排序:Comparator以內部類的形式實現。
代碼如下:
//自定義對象Person類

public class Person {
    private String name;
    private int age;
    public Person() {
        super();

    }
    public Person(String name, int age) {
        super();
        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;
    }
    @Override
    public String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }

}

//測試類

import java.util.Comparator;
import java.util.TreeSet;
public class Test5_1 {

    /**
     * 演示
     * TreeSet存儲自定義對象並遍歷(按照姓名的長度排序)
     */
    public static void main(String[] args) {
        //利用比較器排序(匿名內部類)
        TreeSet<Person> ts = new TreeSet<>(new Comparator<Person>() {

            @Override
            public int compare(Person p1, Person p2) {
                int length = p1.getName().length() - p2.getName().length();
                int num2 = length == 0 ? p1.getName().compareTo(p2.getName()) : length;
                return num2 == 0 ? p1.getAge() - p2.getAge() : num2;
            }
        });
        ts.add(new Person("zhangsan", 23));
        ts.add(new Person("lisi", 25));
        ts.add(new Person("wangwu", 26));
        ts.add(new Person("zhaoliu", 28));
        ts.add(new Person("aaaa", 36));

        System.out.println(ts); 
    }
}
//輸出結果
/*
[Person2 [name=aaaa, age=36], 
Person2 [name=lisi, age=25], 
Person2 [name=wangwu, age=26], 
Person2 [name=zhaoliu, age=28], 
Person2 [name=zhangsan, age=23]]

*/

集合框架之Map

來張Map體系圖:

這裏寫圖片描述
- Map概述:
- 請注意,Map沒有繼承Collection接口,Map提供key到value的映射。一個Map中不能包含相同的key,每個key只能映射一個value。Map接口提供3種集合的視圖,Map的內容可以被當作一組key集合,一組value集合,或者一組key-value映射。

- Map接口和Collection的區別: 
    - 1,Map接口是雙列,而Collection接口是單列。
    - 2,Map體系中鍵是唯一的,Collection的子體系Set是唯一的。
    - 3,Map集合的數據結構的值針對鍵有效,跟值無關。Collection集合的數據結構是針對元素有效。
- Map存儲鍵值時: 
    - 代碼演示,僞代碼如下:
Map<String,Integer> map = new HashMap<>();
Integer i1 = map.put("張三",23);      //返回值爲null
Integer i2 = map.put("李四",24);      //返回值爲null
Integer i2 = map.put("張三",30);      //返回值爲23(出現相同鍵值對時,不會存儲,會覆蓋原來的鍵值對。)
System.out.println(map);    
//輸出結果
/*
{張三=30, 李四=24}
*/
  • Map集合遍歷
    **注意:**Map集合中沒有迭代器
    • A :
      • 1,根據鍵獲取值:首先獲取所有鍵的集合(Set<> set keySet = map.keySet();)接下來就可以使用迭代器了,根據鍵獲取值(map.get(key);
      • 2,增強for循環遍歷(和第一種方法相似)
        - for(k ,key : map.keySet()) { System.out.println(key + " = " + map.get(key));}
    • B:根據鍵值對 對象,獲取鍵和值。
      • 利用entrySet()方法,獲得鍵值對 對象,得到一個Set集合。遍歷Set集合。
      • 代碼如下(來個完整版的):
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

public class MapEntry {

    /**
     * map遍歷:
     *      根據鍵值對 對象,獲取鍵和值。
     */
    public static void main(String[] args) {
        Map<String ,Integer> map = new HashMap<String, Integer>();
        map.put("張三", 23);
        map.put("李四", 24);
        map.put("王五", 25);
        map.put("趙六", 26);
        map.put("馬奇", 27);

        //利用entrySet()方法獲取鍵值對 對象 得到一個set集合(以下兩種寫法,均可)
        //Map.Entry  這是Map接口內又寫了Entry接口
        Set<Map.Entry<String,Integer>> set = map.entrySet();
        //Set<Entry<String,Integer>> set = map.entrySet(); 
        //遍歷鍵值對 對象 set集合
        for (Entry<String, Integer> entry : set) {
            String key = entry.getKey();        //通過鍵值對 對象 的getKey方法獲得鍵
            Integer value = entry.getValue();   //返回與此項對應的值。
            System.out.println(key + "=" + value);
        }
    }
}
  • HashMap集合類
    • 注意:存儲自定義對象時,和HashSet一樣,需要重寫hashCode()和equals()方法。(鍵 是自定義對象,值 是引用數據類型)
  • LinkedHashMap集合類
    • 和LinkedHashSet原理一樣。
  • TreeMap集合類
    • 和TreeMap原理一樣。
  • (面試題)HashMap和Hashtable的區別:
    • 共同點: 底層都是哈希算法,都是雙列集合
    • 不同點:
      • A:
        • 1,HashMap是線程不安全的,效率高,JDK1.2版本
        • 2,Hastable是線程安全的,效率低,JDK1.0版本
      • B:
        • 1,HashMap可以存儲null鍵和值
        • 2,Hastable不可以存儲null鍵和值

注意:Collections 是集合的工具類,與集合沒有關係

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章