1. 程式人生 > >Java常用工具類之集合List、Set、Map

Java常用工具類之集合List、Set、Map

Java常用工具類之集合

一、List

在Collection中,List集合是有序的,Developer可對其中每個元素的插入位置進行精確地控制,可以通過索引來訪問元素,遍歷元素。
在List集合中,我們常用到ArrayList和LinkedList這兩個類。

0x1 ArrayList

ArrayList底層通過陣列實現,隨著元素的增加而動態擴容。而LinkedList底層通過連結串列來實現,隨著元素的增加不斷向連結串列的後端增加節點。

ArrayList是Java集合框架中使用最多的一個類,是一個數組佇列,執行緒不安全集合。

它繼承於AbstractList,實現了List, RandomAccess, Cloneable, Serializable介面。
(1)ArrayList實現List,得到了List集合框架基礎功能;
(2)ArrayList實現RandomAccess,獲得了快速隨機訪問儲存元素的功能,RandomAccess是一個標記介面,沒有任何方法;
(3)ArrayList實現Cloneable,得到了clone()方法,可以實現克隆功能;
(4)ArrayList實現Serializable,表示可以被序列化,通過序列化去傳輸,典型的應用就是hessian協議。

它具有如下特點:

  • 容量不固定,隨著容量的增加而動態擴容(閾值基本不會達到)
  • 有序集合(插入的順序==輸出的順序)
  • 插入的元素可以為null
  • 增刪改查效率更高(相對於LinkedList來說)
  • 執行緒不安全

1、常用方法

A:新增功能
boolean add(E e):向集合中新增一個元素
void add(int index, E element):在指定位置新增元素
boolean addAll(Collection<? extends E> c):向集合中新增一個集合的元素。

B:刪除功能
void clear():刪除集合中的所有元素
E remove(int
index):根據指定索引刪除元素,並把刪除的元素返回 boolean remove(Object o):從集合中刪除指定的元素 boolean removeAll(Collection<?> c):從集合中刪除一個指定的集合元素。 C:修改功能 E set(int index, E element):把指定索引位置的元素修改為指定的值,返回修改前的值。 D:獲取功能 E get(int index):獲取指定位置的元素 Iterator iterator():就是用來獲取集合中每一個元素。 E:判斷功能 boolean isEmpty():判斷集合是否為空。 boolean
contains(Object o):判斷集合中是否存在指定的元素。 boolean containsAll(Collection<?> c):判斷集合中是否存在指定的一個集合中的元素。 F:長度功能 int size():獲取集合中的元素個數 G:把集合轉換成陣列 Object[] toArray():把集合變成陣列。

2、ArrayList基本操作

public class ArrayListTest {
    public static void main(String[] agrs){
        //建立ArrayList集合:
        List<String> list = new ArrayList<String>();
        System.out.println("ArrayList集合初始化容量:"+list.size());

        //新增功能:
        list.add("Hello");
        list.add("world");
        list.add(2,"!");
        System.out.println("ArrayList當前容量:"+list.size());

        //修改功能:
        list.set(0,"my");
        list.set(1,"name");
        System.out.println("ArrayList當前內容:"+list.toString());

        //獲取功能:
        String element = list.get(0);
        System.out.println(element);

        //迭代器遍歷集合:(ArrayList實際的跌倒器是Itr物件)
        Iterator<String> iterator =  list.iterator();
        while(iterator.hasNext()){
            String next = iterator.next();
            System.out.println(next);
        }

        //for迴圈迭代集合:
        for(String str:list){
            System.out.println(str);
        }

        //判斷功能:
        boolean isEmpty = list.isEmpty();
        boolean isContain = list.contains("my");

        //長度功能:
        int size = list.size();

        //把集合轉換成陣列:
        String[] strArray = list.toArray(new String[]{});

        //刪除功能:
        list.remove(0);
        list.remove("world");
        list.clear();
        System.out.println("ArrayList當前容量:"+list.size());
    }
}

3、ArrayList實現公告

//Notice類
import java.util.Date;
public class Notice {
    private int id;//ID
    private String title;//標題
    private String creator;//建立人
    private Date createTime;//建立時間
    public Notice(int id, String title, String creator, Date createTime) {
        super();
        this.id = id;
        this.title = title;
        this.creator = creator;
        this.createTime = createTime;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    public String getTitle() {
        return title;
    }
    public void setTitle(String title) {
        this.title = title;
    }
    public String getCreator() {
        return creator;
    }
    public void setCreator(String creator) {
        this.creator = creator;
    }
    public Date getCreateTime() {
        return createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }   
}


//Notice測試類
import java.util.ArrayList;
import java.util.Date;

public class NoticeTest {

    public static void main(String[] args) {
        // 建立Notice類的物件,生成三條公告
        Notice notice1 = new Notice(1, "歡迎來到慕課網!", "管理員", new Date());
        Notice notice2 = new Notice(2, "請同學們按時提交作業!", "老師", new Date());
        Notice notice3 = new Notice(3, "考勤通知!", "老師", new Date());

        // 新增公告
        ArrayList noticeList = new ArrayList();
        noticeList.add(notice1);
        noticeList.add(notice2);
        noticeList.add(notice3);

        // 顯示公告
        System.out.println("公告的內容為:");
        for (int i = 0; i < noticeList.size(); i++) {
            System.out.println(i + 1 + ":" + ((Notice) (noticeList.get(i))).getTitle());
        }

        System.out.println("**************************************");
        // 在第一條公告後面新增一條新公告
        Notice notice4 = new Notice(4, "線上編輯器可以使用啦!", "管理員", new Date());
        noticeList.add(1, notice4);

        // 顯示公告
        System.out.println("公告的內容為:");
        for (int i = 0; i < noticeList.size(); i++) {
            System.out.println(i + 1 + ":" + ((Notice) (noticeList.get(i))).getTitle());
        }

        System.out.println("**************************************");
        // 刪除按時提交作業的公告
        noticeList.remove(2);
        // 顯示公告
        System.out.println("刪除公告後的內容為:");
        for (int i = 0; i < noticeList.size(); i++) {
            System.out.println(i + 1 + ":" + ((Notice) (noticeList.get(i))).getTitle());
        }

        //將第二條公告改為:Java線上編輯器可以使用啦!
        System.out.println("**************************************");
        //修改第二條公告中title的值
        notice4.setTitle("Java線上編輯器可以使用啦!");
        noticeList.set(1, notice4);
        System.out.println("修改後公告的內容為:");
        for (int i = 0; i < noticeList.size(); i++) {
            System.out.println(i + 1 + ":" + ((Notice) (noticeList.get(i))).getTitle());
        }
    }
}

0x2 LinkedList

LinkedList是一個雙向連結串列,每一個節點都擁有指向前後節點的引用。相比於ArrayList來說,LinkedList的隨機訪問效率更低。

它繼承AbstractSequentialList,實現了List, Deque, Cloneable, Serializable介面。
(1)LinkedList實現List,得到了List集合框架基礎功能;
(2)LinkedList實現Deque,Deque 是一個雙向佇列,也就是既可以先入先出,又可以先入後出,說簡單些就是既可以在頭部新增元素,也可以在尾部新增元素;
(3)LinkedList實現Cloneable,得到了clone()方法,可以實現克隆功能;
(4)LinkedList實現Serializable,表示可以被序列化,通過序列化去傳輸,典型的應用就是hessian協議。

1、常用方法

方法名 說明
boolean add(E e) 將指定元素新增到此列表的結尾
void add(int index, E element) 在此列表中指定的位置插入指定的元素
boolean addAll(Collection c) 新增指定 collection 中的所有元素到此列 表的結尾
boolean addAll(int index, Collection c) 將指定 collection 中的所有元素從指定位 置開始插入此列表
void addFirst(E e) 將指定元素插入此列表的開頭
void addLast(E e) 將指定元素新增到此列表的結尾
void clear() 從此列表中移除所有元素
boolean contains(Object o) 如果此列表包含指定元素,則返回 true
E get(int index) 返回此列表中指定位置處的元素
E getFirst() 返回此列表的第一個元素
E getLast() 返回此列表的最後一個元素
int indexOf(Object o) 返回此列表中首次出現的指定元素的索引, 如果此列表中不包含該元素,則返回 -1
int lastIndexOf(Object o) 返回此列表中最後出現的指定元素的索引, 如果此列表中不包含該元素,則返回 -1
E peek() 獲取但不移除此列表的頭(第一個元素)
E peekFirst() 獲取但不移除此列表的第一個元素;如果此 列表為空,則返回 null
E peekLast() 獲取但不移除此列表的最後一個元素;如果 此列表為空,則返回 null
E poll() 獲取並移除此列表的頭(第一個元素)
E pollFirst() 獲取並移除此列表的第一個元素;如果此列 表為空,則返回 null
E pollLast() 獲取並移除此列表的最後一個元素;如果此 列表為空,則返回 null
E pop() 從此列表所表示的堆疊處彈出一個元素
E remove() 獲取並移除此列表的頭(第一個元素)
boolean remove(Object o) 從此列表中移除首次出現的指定元素(如果 存在)
E removeFirst() 移除並返回此列表的第一個元素
E set(int index, E element) 將此列表中指定位置的元素替換為指定的 元素
int size() 返回此列表的元素數
Object[] toArray() 返回以適當順序(從第一個元素到最後一個 元素)包含此列表中所有元素的陣列

2、基本操作

public class LinkedListTest {
    public static void main(String[] agrs){
        List<String> linkedList = new LinkedList<String>();
        System.out.println("LinkedList初始容量:"+linkedList.size());

        //新增功能:
        linkedList.add("my");
        linkedList.add("name");
        linkedList.add("is");
        linkedList.add("jiaboyan");
        System.out.println("LinkedList當前容量:"+ linkedList.size());

        //修改功能:
        linkedList.set(0,"hello");
        linkedList.set(1,"world");
        System.out.println("LinkedList當前內容:"+ linkedList.toString());

        //獲取功能:
        String element = linkedList.get(0);
        System.out.println(element);

        //遍歷集合:(LinkedList實際的跌倒器是ListItr物件)
        Iterator<String> iterator =  linkedList.iterator();
        while(iterator.hasNext()){
            String next = iterator.next();
            System.out.println(next);
        }
        //for迴圈迭代集合:
        for(String str:linkedList){
            System.out.println(str);
        }

        //判斷功能:
        boolean isEmpty = linkedList.isEmpty();
        boolean isContains = linkedList.contains("jiaboyan");

        //長度功能:
        int size = linkedList.size();

        //刪除功能:
        linkedList.remove(0);
        linkedList.remove("jiaboyan");
        linkedList.clear();
        System.out.println("LinkedList當前容量:" + linkedList.size());
    }
}

二、Set

Set繼承於Collection介面,是一個不允許出現重複元素,並且無序的集合,主要有HashSet和TreeSet兩大實現類。

在判斷重複元素的時候,Set集合會呼叫hashCode()和equal()方法來實現。

HashSet是雜湊表結構,主要利用HashMap的key來儲存元素,計算插入元素的hashCode來獲取元素在集合中的位置;

TreeSet是紅黑樹結構,每一個元素都是樹中的一個節點,插入的元素都會進行排序;

Set集合框架結構:

0x1 Set常用方法

public interface Set<E> extends Collection<E> {

    A:新增功能
    boolean add(E e);
    boolean addAll(Collection<? extends E> c);

    B:刪除功能
    boolean remove(Object o);
    boolean removeAll(Collection<?> c);
    void clear();

    C:長度功能
    int size();

    D:判斷功能
    boolean isEmpty();
    boolean contains(Object o);
    boolean containsAll(Collection<?> c);
    boolean retainAll(Collection<?> c); 

    E:獲取Set集合的迭代器:
    Iterator<E> iterator();

    F:把集合轉換成陣列
    Object[] toArray();
    <T> T[] toArray(T[] a);

    //判斷元素是否重複,為子類提高重寫方法
    boolean equals(Object o);
    int hashCode();
}

0x2 HashSet

HashSet實現Set介面,底層由HashMap(後面講解)來實現,為雜湊表結構,新增元素相當於HashMap的key,value預設為一個固定的Object。在我看來,HashSet相當於一個閹割版的HashMap;

當有元素插入的時候,會計算元素的hashCode值,將元素插入到雜湊表對應的位置中來;

它繼承於AbstractSet,實現了Set, Cloneable, Serializable介面。

(1)HashSet繼承AbstractSet類,獲得了Set介面大部分的實現,減少了實現此介面所需的工作,實際上是又繼承了AbstractCollection類;

(2)HashSet實現了Set介面,獲取Set介面的方法,可以自定義具體實現,也可以繼承AbstractSet類中的實現;

(3)HashSet實現Cloneable,得到了clone()方法,可以實現克隆功能;

(4)HashSet實現Serializable,表示可以被序列化,通過序列化去傳輸,典型的應用就是hessian協議。

具有如下特點:

  • 不允許出現重複因素;
  • 允許插入Null值;
  • 元素無序(新增順序和遍歷順序不一致);
  • 執行緒不安全,若2個執行緒同時操作HashSet,必須通過程式碼實現同步;

HashSet底層由HashMap實現,插入的元素被當做是HashMap的key,根據hashCode值來確定集合中的位置,由於Set集合中並沒有角標的概念,所以並沒有像List一樣提供get()方法。當獲取HashSet中某個元素時,只能通過遍歷集合的方式進行equals()比較來實現;

public class HashSetTest {
    public static void main(String[] agrs){
        //建立HashSet集合:
        Set<String> hashSet = new HashSet<String>();
        System.out.println("HashSet初始容量大小:"+hashSet.size());

        //元素新增:
        hashSet.add("my");
        hashSet.add("name");
        hashSet.add("is");
        hashSet.add("jiaboyan");
        hashSet.add(",");
        hashSet.add("hello");
        hashSet.add("world");
        hashSet.add("!");
        System.out.println("HashSet容量大小:"+hashSet.size());

        //迭代器遍歷:
        Iterator<String> iterator = hashSet.iterator();
        while (iterator.hasNext()){
            String str = iterator.next();
            System.out.println(str);
        }
        //增強for迴圈
        for(String str:hashSet){
            if("jiaboyan".equals(str)){
                System.out.println("你就是我想要的元素:"+str);
            }
            System.out.println(str);
        }

        //元素刪除:
        hashSet.remove("jiaboyan");
        System.out.println("HashSet元素大小:" + hashSet.size());
        hashSet.clear();
        System.out.println("HashSet元素大小:" + hashSet.size());

        //集合判斷:
        boolean isEmpty = hashSet.isEmpty();
        System.out.println("HashSet是否為空:" + isEmpty);
        boolean isContains = hashSet.contains("hello");
        System.out.println("HashSet是否為空:" + isContains);
    }
}

0x3 Set寵物貓案例

Cat類

public class Cat {
    private String name; //名字
    private int month; //年齡
    private String species;//品種

    //構造方法
    public Cat(String name, int month, String species) {
        super();
        this.name = name;
        this.month = month;
        this.species = species;
    }
    //getter與setter方法
    public String getName() {
        return name;
    }

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

    public int getMonth() {
        return month;
    }

    public void setMonth(int month) {
        this.month = month;
    }

    public String getSpecies() {
        return species;
    }

    public void setSpecies(String species) {
        this.species = species;
    }

    //重寫toString方法
    @Override
    public String toString() {
        return "[姓名:" + name + ", 年齡:" + month + ", 品種:" + species + "]";
    }
    //重寫HashSet
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + month;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + ((species == null) ? 0 : species.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        //判斷物件是否相等,相等則返回true,不用繼續比較屬性了
        if(this==obj)
            return true;
        //判斷obj是否是Cat類的物件
        if(obj.getClass()==Cat.class){
            Cat cat=(Cat)obj;
            return cat.getName().equals(name)&&(cat.getMonth()==month)&&(cat.getSpecies().equals(species));
        }   
        return false;
    }
}

Cat測試類


import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class CatTest {

    public static void main(String[] args) {
        // 定義寵物貓物件
        Cat huahua = new Cat("花花", 12, "英國短毛貓");
        Cat fanfan = new Cat("凡凡", 3, "中華田園貓");
        // 將寵物貓物件放入HashSet中
        Set<Cat> set = new HashSet<Cat>();
        set.add(huahua);
        set.add(fanfan);
        // 顯示寵物貓資訊
        Iterator<Cat> it = set.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }

        // 再新增一個與花花屬性一樣的貓
        Cat huahua01 = new Cat("花花", 12, "英國短毛貓");
        set.add(huahua01);
        System.out.println("**********************************");
        System.out.println("新增重複資料後的寵物貓資訊:");
        it = set.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }

        System.out.println("**********************************");
        // 重新插入一個新寵物貓
        Cat huahua02 = new Cat("花花二代", 2, "英國短毛貓");
        set.add(huahua02);
        System.out.println("新增花花二代後的寵物貓資訊:");
        it = set.iterator();
        while (it.hasNext()) {
            System.out.println(it.next());
        }

        System.out.println("**********************************");
        // 在集合中查詢花花的資訊並輸出
        if (set.contains(huahua)) {
            System.out.println("花花找到了!");
            System.out.println(huahua);
        } else {
            System.out.println("花花沒找到!");
        }
        // 在集合中使用名字查詢花花的資訊
        System.out.println("**********************************");
        System.out.println("通過名字查詢花花資訊");
        boolean flag = false;
        Cat c = null;
        it = set.iterator();
        while (it.hasNext()) {
            c = it.next();
            if (c.getName().equals("花花")) {
                flag = true;// 找到了
                break;
            }
        }
        if (flag) {
            System.out.println("花花找到了");
            System.out.println(c);
        } else {
            System.out.println("花花沒找到");
        }

        // 刪除花花二代的資訊並重新輸出
        for (Cat cat : set) {
            if ("花花二代".equals(cat.getName())) {
                set.remove(cat);
break;          }
        }
        System.out.println("**********************************");

        System.out.println("刪除花花二代後的資料");
        for(Cat cat:set){
            System.out.println(cat);
        }
        //刪除集合中的所有寵物貓資訊
        System.out.println("**********************************");
        boolean flag1=set.removeAll(set);
        if(set.isEmpty()){
            System.out.println("貓都不見了。。。");
        }else{
            System.out.println("貓還在。。。");
        }
    }
}

三、Map