java基礎學習之九:集合型別Set/List/Map

趙明威發表於2016-05-14

一、Java集合介面、集合類

Java中實現了程式設計中的傳統的資料結構,現在你不需要專門寫一套什麼連結串列、佇列、字典這種資料結構了,本合集將講解一下Java的集合類框架,以及他們之間的繼承關係。

集合框架一覽

集合框架一覽

Java 集合定義了兩種基本的資料結構,

  • 一種是 Collection,表示一組物件的集合
  • 另一種是 Map

    1. Set 是一種 Collection,不過其中沒有重複的物件
    2. List 也是一種 Collection,其中的元素按順序排列(不過可以有重複)
    3. Map和Collection位於同一級別,這就是大家常說的字典.

二、Collection

子介面
Set,List
集合中只能放置物件的引用,不能放置原生資料型別,
我們需要使用原生資料型別的封裝類才能加入到集合中

建立幾個例項

    // 建立幾個集合.由於Collection是介面,所以要用它的子類來例項化
    Collection<String> c = new HashSet<String>(); // 一個空集

    // 稍後會介紹這些實用方法
    // 注意,使用時要留意一些細節
    Collection<String> d = new ArrayList<String>(20);
    Collection<String> e = Collections.singleton("three");
  1. Iterator介面

所有實現Collection介面容器類都有一個iterator方法用以返回一個實現iterator介面物件。iterator物件稱迭代器,方便對實現對容器內元素的遍歷操作。

現在此處講解最基本的遍歷方法,其他具體的方法在具體的子類中應用

Iterator介面方法

boolean hasNext() 判斷右邊是否有元素
Object next() //返回遊標右邊的元素,且將遊標移動到下一個位置。 jdk1.4以前是Object jdk1.5以後是

泛型E next()取到下一個位置

void remove() 刪除遊標左邊的元素,只可以執行一次。

介面中只有方法的定義,沒有方法的實現。

iterator通俗說:統一遍歷所有元素的方法

Iterator物件的remove方法是在迭代器過程中刪除元素的唯一的安全方法。Iterator 在執行中進行鎖定.

    Set<String> staff = new HashSet<String>();
    staff.add("Amy");
    staff.add("Bob");
    staff.add("Carl");
    Iterator<String> iterStaff = staff.iterator();
    //遍歷方法 Iterator
    while(iterStaff.hasNext()){
        String name =  iterStaff.next();
        iterStaff.remove();
        System.out.println(name);
        System.out.println(Arrays.toString(staff.toArray()));
    }

結果

Amy
[Bob, Carl]
Bob
[Carl]
Carl
[]

三、Set

1.HashSet

  • 它不允許出現重複元素
  • 不對集合進行排序,也不保證按照插入資料順序
  • 允許包含值為null的元素,但最多隻能有一個null元素。(有第一條規則可知)

    1. 常用方法

      按照定義,Set 介面繼承 Collection 介面,而且它不允許集合中存在重複項。所有原始方法都是現成的,沒有引入新方法。具體的 Set 實現類依賴新增的物件的 equals() 方法來檢查等同性。

各個方法的作用描述:

boolean add(E e)新增元素,新增成功返回true, 如果set中不存在指定元素,則向set加入 ;

    Set<String> staff = new HashSet<String>();
    staff.add("Amy"); //true
    staff.add("Bob"); //true
    System.out.println(staff.add("Carl"));//true
    System.out.println(staff.add("Carl"));//false

public int size() :返回set中元素的數目,如果set包含的元素數大於Integer.MAX_VALUE,返回Integer.MAX_VALUE;

   staff.size();//3

public boolean isEmpty() :如果set中不含元素,返回true ;

    Set<String> staff = new HashSet<String>();
    System.out.println(staff.isEmpty()); //true
    staff.add("Amy"); 
    staff.add("Bob");
    System.out.println(staff.isEmpty()); //false

public boolean contains(Object o) :如果set包含指定元素,返回true ;

    staff.contains("Bob");//true
    staff.contains("BoB");//false

public Iterator iterator() : 返回set中元素的迭代器,元素返回沒有特定的順序,除非set提高該保證的某些類的例項 ;

public boolean remove(Object o) :如果set中存在指定元素,則從set中刪除 ;

    Set<String> staff = new HashSet<String>();

    staff.add("Amy"); //true
    staff.add("Bob"); //true
    staff.add("Carl");//true

    staff.remove("Amy");

    System.out.println(Arrays.toString(staff.toArray()));

結果輸出:

    [Carl, Bob]

public boolean removeAll(Collection c) :如果set包含指定集合,則從set中刪除指定集合的所有元素

Set staff = new HashSet(); staff.add("Amy"); staff.add("Bob"); staff.add("Carl");

    Set<String> staff1 = new HashSet<String>();
    staff1.add("Bob");
    staff1.add("Carl");
    staff1.add("c");

    //刪除之前
    System.out.println(Arrays.toString(staff.toArray()));
    //除去staff 和 staff1 公共的集合
    staff.removeAll(staff1);

    //刪除之後
    System.out.println(Arrays.toString(staff.toArray()));

結果:

[Amy, Carl, Bob]
[Amy]

public void clear() :從set中刪除所有元素;

遍歷方法:

    Set<String> staff = new HashSet<String>();
    staff.add("Amy");
    staff.add("Bob");
    staff.add("Carl");

    Iterator<String> iterStaff = staff.iterator();
    //遍歷方法1  Iterator
    while(iterStaff.hasNext()){
        String name =  iterStaff.next();
        System.out.println(name);
    }

另外一種增強型的for迴圈

    for(String name : staff){
        System.out.println(name);
    }

僅僅檢視元素的話:

   System.out.println(Arrays.toString(staff.toArray()));

四、List

List 連結串列主要包括 ArrayList 和 LinkedList 以及 Vector,允許連結串列元素重複

1、ArrayList

如果沒有頻繁的刪除插入操作,又不用考慮多執行緒問題,優先選擇ArrayList,主要用於查詢,

a.基本方法

   //宣告方式
    List<String> staff = new ArrayList<>();

新增資料 boolean add(E e) ,資料改變的話則返回true

    boolean flag = false;
    flag = staff.add("Amy"); //true
    flag = staff.add("Bob"); //true
    flag = staff.add("Carl");//true

對具體位置進行新增 void add(int index, E e) 無返回值

    staff.add(0,"2");
    System.out.println(staff.get(0));

根據索引獲得資料get方法, E get(int index), 返回值型別就是宣告時候的泛型型別

    String name = staff.get(0);//Amy

陣列與List相互轉換的方法,public T[] toArray(T[] a)   a 是要儲存列表元素的陣列,如果它足夠大的話;否則,它是一個為儲存列表元素而分配的、具有相同執行時型別的新陣列。另外也有Object[] toArray();方法,但是對於它來說,得到的資料要強轉成對應的型別.

     //第一種方法
    String[] names = new String[staff.size()];
    staff.toArray(names);
    System.out.println(Arrays.toString(names));
    //第二種方法這種方法刪掉,報異常
   //java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
    //String[] names = (String[]) staff.toArray();

對於陣列轉化成List, 呼叫Arrays的asList方法, List asList(T... a)

    List<String> staff = new ArrayList<>();
    String[] names = {"Amy,Bob,Carl"};
    //<T> List<T> asList(T... a)
    //staff = Arrays.asList(names);
    //也可以staff = Arrays.asList("Amy","Bob","Carl");

set()方法,E set(int index, E element),根據索引位置,對資料進行改變,返回原來位置的元素

    String name = staff.set(0,"AAAAA");
    System.out.println("name : "+name);//name : Amy

set主要用於對資料進行交換,比如:

    System.out.println(Arrays.toString(staff.toArray()));
    staff.set(1,staff.set(0,staff.get(1)));
    System.out.println(Arrays.toString(staff.toArray()));

結果

[Amy, Bob, Carl]
[Bob, Amy, Carl]

remove() 方法, E remove(int index),根據索引刪除特定的值,並且返回刪除的值

    String name = staff.remove(2);

addAll(list)方法,在原來的連結串列最後面追加連結串列 boolean addAll(Collection<? extends E> c);

    List<String> company = new ArrayList<>();
    company.add("12");
    company.addAll(staff);//[12, Amy, Bob, Carl]

addAll(index,list)在index處插入一個連結串列,boolean addAll(int index, Collection<? extends E> c)

    List<String> company = new ArrayList<>();
    company.add("12");
    company.addAll(1,staff);
    company.add("23");//[12, Amy, Bob, Carl, 23]

b.遍歷方法

    List<String> staff = new ArrayList<>();
    staff.add("Amy");
    staff.add("Bob");
    staff.add("Carl");
    Iterator<String> iterStaff = staff.iterator();
    //遍歷方法 Iterator
    while(iterStaff.hasNext()){
        String name =  iterStaff.next();
        System.out.println(name);
    }

    //在Java1.5後 可以使用 for each 迴圈
    for (String name : staff){
        System.out.println(name);
    }

    //如果需要list的索引號,則使用普通的迴圈即可
    int len = staff.size();
    for (int i = 0; i < len; i++){
        System.out.println("第 "+i+ "個員工的名字是:"+staff.get(i));
    }

  //單純的想看看staff的元素的話,可以簡單粗暴的
  System.out.println(Arrays.toString(staff.toArray(new String[]{})));

五、Map

1.HashMap

對於 HashMap 而言,系統 key-value 當成一個整體進行處理,系統總是根據 Hash 演算法來計算 key-value 的儲存位置,這樣可以保證能快速存、取 Map 的 key-value 對。

HashMap 無序

例項化,put(),返回 原來的key對應的value,如果原來不存在這個key 則返回null

    HashMap<String , Double> classMap = new HashMap<String , Double>();
   Double d =  classMap.put("語文", 80.0);
    classMap.put("數學", 89.0);
    classMap.put("英語", 78.2);
    System.out.println(d); 
    d =  classMap.put("語文", 60.0);
    System.out.println(d);

結果:

 null
 80.0

get()方法, V get(Object key) 通過 key值 獲得value,若果key不存在,返回null

    classMap.get("語文");//60.0
    classMap.get("思想品德");//null

為了防止空指標異常:可以用containsKey,方法判斷是否存在key,boolean containsKey(Object key)

    classMap.containsKey("思想品德");//false

isEmpty()判斷Map是否為空,空則 返回true,非空 返回 false

    classMap.isEmpty();//false
    HashMap<String , Double> classMap2 = new HashMap<String , Double>();
    classMap2.isEmpty();//

size() 返回Map的長度,

    classMap.size();

遍歷方式

第一種:效率較低

    Set<String> keys = classMap.keySet();
    for (String key : keys){
        System.out.println(key+":"+classMap.get(key));
    }

第二種效率高:

    //classMap.entrySet();
    for (Map.Entry entry : classMap.entrySet()){
        System.out.println(entry.getKey()+":"+entry.getValue());
    }

具體參見文章: keySet 與entrySet 遍歷HashMap效能差別

相關文章