Java基礎(chǔ):集合框架

Java類中集合的關(guān)系圖

1. 集合類概述

1.1 為什么出現(xiàn)集合類?

面向?qū)ο笳Z言對(duì)事物的體現(xiàn)都是以對(duì)象的形式,所以為了方便對(duì)多個(gè)對(duì)象的操作,Java就提供了集合類。

1.2 數(shù)組和集合類同是容器,有何不同?

1.3 集合類的特點(diǎn)

集合只用于存儲(chǔ)對(duì)象,集合長(zhǎng)度是可變的,集合可以存儲(chǔ)不同類型的對(duì)象。

2. Collection接口概述

Collection 層次結(jié)構(gòu)中的根接口。Collection 表示一組對(duì)象,這些對(duì)象也稱為 collection 的元素。一些 collection 允許有重復(fù)的元素,而另一些則不允許。一些 collection 是有序的,而另一些則是無序的。

3. Collection接口成員方法

4. Collection實(shí)現(xiàn)類

4.1 List接口概述

有序的 collection(也稱為序列)。此接口的用戶可以對(duì)列表中每個(gè)元素的插入位置進(jìn)行精確地控制。用戶可以根據(jù)元素的整數(shù)索引(在列表中的位置)訪問元素,并搜索列表中的元素。與 set 不同,列表通常允許重復(fù)的元素。

4.1.1 ArrayList類概述

底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組,查詢快,增刪慢,線程不安全,效率高。

4.1.2 Vector類概述

底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組,查詢快,增刪慢,線程安全,效率低。

4.1.3 Vector類特有功能

  • public void addElement(E obj):添加元素
  • public E elementAt(int index):根據(jù)索引獲取元素
  • public Enumeration elements():獲取所有的元素

4.1.4 LinkedList類概述

底層數(shù)據(jù)結(jié)構(gòu)是鏈表,查詢慢,增刪快,線程不安全,效率高

方法聲明 功能描述
public void addFirst(E e) 將指定元素插入此列表的開頭
public voidaddLast(E e) 將指定元素添加到此列表的結(jié)尾
public E getFirst() 將指定元素添加到此列表的結(jié)尾
public E getLast() 獲取集合的最后一個(gè)元素
public E removeFirst() 刪除集合的第一個(gè)元素
public E removeLast() 刪除最后一個(gè)元素

代碼示例:使用LinkedList來模擬一個(gè)棧數(shù)據(jù)結(jié)構(gòu)

package cn.itcast;

import java.util.LinkedList;

/*
 *使用LinkedList模擬棧數(shù)據(jù)結(jié)構(gòu)的集合,并測(cè)試
 *1、棧的特點(diǎn)先進(jìn)后出
 *2、 LinkedList的特有添加功能addFirst()
 */
class MyStack {
    private LinkedList link;

    public MyStack() {
        link = new LinkedList();
    }

    public void add(Object obj) {
        // 將指定元素插入此列表的開頭
        link.addFirst(obj);
    }

    public Object get() {
        // 移除并返回此列表的第一個(gè)元素。
        // return link.getFirst();
        return link.removeFirst();
    }

    public boolean isEmpty() {
        return link.isEmpty();
    }
}

/*
 * MyStack的測(cè)試
 */
public class MyStackDemo {
    public static void main(String[] args) {
        // 創(chuàng)建集合對(duì)象
        MyStack ms = new MyStack();
        // 添加元素
        ms.add("hello");
        ms.add("world");
        ms.add("java");
        ms.add("android");
        ms.add("javase");
        while (!ms.isEmpty()) {
            System.out.println(ms.get());
        }
    }
}

運(yùn)行結(jié)果:


4.2 Set接口概述

一個(gè)不包含重復(fù)元素的 collection,無序。

哈希表確定元素是否相同

1、 判斷的是兩個(gè)元素的哈希值是否相同。
如果相同,再判斷兩個(gè)對(duì)象的內(nèi)容是否相同。

2、 判斷哈希值相同,其實(shí)判斷的是對(duì)象的HashCode方法。判斷內(nèi)容相同,用的是equals方法。

4.2.1 HashSet類概述

  • 不保證 set 的迭代順序,特別是它不保證該順序恒久不變。
  • HashSet如何保證元素唯一性
  • 底層數(shù)據(jù)結(jié)構(gòu)是哈希表(元素是鏈表的數(shù)組)
  • 哈希表依賴于哈希值存儲(chǔ)
  • 添加功能底層依賴兩個(gè)方法:int hashCode()、boolean equals(Object obj)

HashSet存儲(chǔ)元素保證唯一性的代碼及圖解:

package cn.itcast;

import java.util.HashSet;

class Dog {
    private String name;
    private int age;
    private String color;
    private char sex;

    public Dog() {
        super();
    }

    public Dog(String name, int age, String color, char sex) {
        super();
        this.name = name;
        this.age = age;
        this.color = color;
        this.sex = sex;
    }

    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;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public char getSex() {
        return sex;
    }

    public void setSex(char sex) {
        this.sex = sex;
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((color == null) ? 0 : color.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + sex;
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Dog other = (Dog) obj;
        if (age != other.age)
            return false;
        if (color == null) {
            if (other.color != null)
                return false;
        } else if (!color.equals(other.color))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (sex != other.sex)
            return false;
        return true;
    }

}

/*
 * HashSet集合存儲(chǔ)自定義對(duì)象并遍歷。如果對(duì)象的成員變量值相同即為同一個(gè)對(duì)象
 * 
 * 注意了: 你使用的是HashSet集合,這個(gè)集合的底層是哈希表結(jié)構(gòu)。 而哈希表結(jié)構(gòu)底層依賴:hashCode()和equals()方法。
 * 如果你認(rèn)為對(duì)象的成員變量值相同即為同一個(gè)對(duì)象的話,你就應(yīng)該重寫這兩個(gè)方法。 如何重寫呢?不同擔(dān)心,自動(dòng)生成即可。
 */
public class DogDemo {
    public static void main(String[] args) {
        // 創(chuàng)建集合對(duì)象
        HashSet<Dog> hs = new HashSet<Dog>();

        // 創(chuàng)建狗對(duì)象
        Dog d1 = new Dog("秦檜", 25, "紅色", '男');
        Dog d2 = new Dog("高俅", 22, "黑色", '女');
        Dog d3 = new Dog("秦檜", 25, "紅色", '男');
        Dog d4 = new Dog("秦檜", 20, "紅色", '女');
        Dog d5 = new Dog("魏忠賢", 28, "白色", '男');
        Dog d6 = new Dog("李蓮英", 23, "黃色", '女');
        Dog d7 = new Dog("李蓮英", 23, "黃色", '女');
        Dog d8 = new Dog("李蓮英", 23, "黃色", '男');

        // 添加元素
        hs.add(d1);
        hs.add(d2);
        hs.add(d3);
        hs.add(d4);
        hs.add(d5);
        hs.add(d6);
        hs.add(d7);
        hs.add(d8);

        // 遍歷
        for (Dog d : hs) {
            System.out.println(d.getName() + "---" + d.getAge() + "---"
                    + d.getColor() + "---" + d.getSex());
        }
    }
}

運(yùn)行結(jié)果:


4.2.2 LinkedHashSet類概述

元素有序唯一,由鏈表保證元素有序,由哈希表保證元素唯一。

4.3 TreeSet類概述

使用元素的自然順序?qū)υ剡M(jìn)行排序,或者根據(jù)創(chuàng)建 set 時(shí)提供的 Comparator 進(jìn)行排序,具體取決于使用的構(gòu)造方法。

  • TreeSet是如何保證元素的排序和唯一性
    底層數(shù)據(jù)結(jié)構(gòu)是紅黑樹(紅黑樹是一種自平衡的二叉樹)

  • TreeSet判斷元素唯一性的方式
    就是根據(jù)比較方法的返回結(jié)果是否是0,是0,就是相同元素,不存。

  • TreeSet對(duì)元素進(jìn)行排序的方式一
    讓元素自身具備比較功能,元素就需要實(shí)現(xiàn)Comparable接口,覆蓋compareTo方法。
    如果不要按照對(duì)象中具備的自然順序進(jìn)行排序。如果對(duì)象中不具備自然順序。怎么辦?

  • 可以使用TreeSet集合第二種排序方式
    讓集合自身具備比較功能,定義一個(gè)類實(shí)現(xiàn)Comparator接口,覆蓋compare方法。將該類對(duì)象作為參數(shù)傳遞給TreeSet集合的構(gòu)造函數(shù)。

TreeSet存儲(chǔ)元素自然排序和唯一的圖解:

package cn.itcast;

import java.util.Comparator;
import java.util.TreeSet;

class Student {
    private String name;
    private int age;

    public Student() {
        super();
    }

    public Student(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;
    }
}

class MyComparator implements Comparator<Student> {

    public int compare(Student s1, Student s2) {
        // int num = this.name.length() - s.name.length();
        // this -- s1
        // s -- s2
        // 姓名長(zhǎng)度
        int num = s1.getName().length() - s2.getName().length();
        // 姓名內(nèi)容
        int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
        // 年齡
        int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
        return num3;
    }

}

/*
 * 需求:請(qǐng)按照姓名的長(zhǎng)度排序
 * 
 * TreeSet集合保證元素排序和唯一性的原理 唯一性:是根據(jù)比較的返回是否是0來決定。 排序: A:自然排序(元素具備比較性)
 * 讓元素所屬的類實(shí)現(xiàn)自然排序接口 Comparable B:比較器排序(集合具備比較性) 讓集合的構(gòu)造方法接收一個(gè)比較器接口的子類對(duì)象 Comparator
 */
public class TreeSetDemo {
    public static void main(String[] args) {
        // 創(chuàng)建集合對(duì)象
        // TreeSet<Student> ts = new TreeSet<Student>(); //自然排序
        // public TreeSet(Comparator comparator) //比較器排序
        // TreeSet<Student> ts = new TreeSet<Student>(new MyComparator());

        // 如果一個(gè)方法的參數(shù)是接口,那么真正要的是接口的實(shí)現(xiàn)類的對(duì)象
        // 而匿名內(nèi)部類就可以實(shí)現(xiàn)這個(gè)東西
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            public int compare(Student s1, Student s2) {
                // 姓名長(zhǎng)度
                int num = s1.getName().length() - s2.getName().length();
                // 姓名內(nèi)容
                int num2 = num == 0 ? s1.getName().compareTo(s2.getName())
                        : num;
                // 年齡
                int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
                return num3;
            }
        });

        // 創(chuàng)建元素
        Student s1 = new Student("linqingxia", 27);
        Student s2 = new Student("zhangguorong", 29);
        Student s3 = new Student("wanglihong", 23);
        Student s4 = new Student("linqingxia", 27);
        Student s5 = new Student("liushishi", 22);
        Student s6 = new Student("wuqilong", 40);
        Student s7 = new Student("fengqingy", 22);
        Student s8 = new Student("linqingxia", 29);

        // 添加元素
        ts.add(s1);
        ts.add(s2);
        ts.add(s3);
        ts.add(s4);
        ts.add(s5);
        ts.add(s6);
        ts.add(s7);
        ts.add(s8);

        // 遍歷
        for (Student s : ts) {
            System.out.println(s.getName() + "---" + s.getAge());
        }
    }
}

運(yùn)行結(jié)果:


4.4 集合的遍歷

迭代:是取出集合中元素的一種方式。

而每一個(gè)容器的數(shù)據(jù)結(jié)構(gòu)不同,所以取出的動(dòng)作細(xì)節(jié)也不一樣。但是都具有共性內(nèi)容: 判斷和取出。那么就可以將這些共性抽取。那么這些內(nèi)部類都符合一個(gè)規(guī)則(或者說都抽取出來一個(gè)規(guī)則)。該規(guī)則就是Iterator。通過一個(gè)對(duì)外提供的方法:iterator();,來獲取集合的取出對(duì)象。因?yàn)镃ollection中有iterator方法,所以每一個(gè)子類集合對(duì)象都具備迭代器。

迭代的常見操作


PS:在迭代時(shí)循環(huán)中next調(diào)用一次,就要hasNext判斷一次。

并發(fā)修改異常,原因:迭代器依賴于集合存在,修改集合元素而迭代器卻不知道。

解決方法:

A:迭代器迭代元素,迭代器修改。因?yàn)镮terator沒有添加功能,所以使用其子接口ListIterator,元素在迭代元素的后面添加。
B:集合遍歷元素,集合修改元素(普通for和get(index)結(jié)合),元素在最后添加

package cn.itcast;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;

/*
 * 問題:有一個(gè)集合,如下,請(qǐng)問,我想判斷里面有沒有"world"這個(gè)元素,如果有,我就添加一個(gè)"javaee"元素,請(qǐng)寫代碼實(shí)現(xiàn)。
 * 
 * ConcurrentModificationException:當(dāng)方法檢測(cè)到對(duì)象的并發(fā)修改,但不允許這種修改時(shí),拋出此異常。 
 * 產(chǎn)生的原因:
 * 迭代器是依賴于集合而存在的,在判斷成功后,集合的中新添加了元素,而迭代器卻不知道,所以就報(bào)錯(cuò)了,這個(gè)錯(cuò)叫并發(fā)修改異常。
 * 其實(shí)這個(gè)問題描述的是:迭代器遍歷元素的時(shí)候,通過集合是不能修改元素的。
 * 如何解決呢?
 * A:迭代器迭代元素,迭代器修改元素,元素是跟在剛才迭代的元素后面的。
 * B:集合遍歷元素,集合修改元素(普通for),元素在最后添加的。
 */
public class ListIteratorDemo {
    public static void main(String[] args) {
        // 創(chuàng)建List集合對(duì)象
        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();
        // if ("world".equals(s)) {
        // list.add("javaee");
        // }
        // }

        // 方式1:迭代器迭代元素,迭代器修改元素
        // 而Iterator迭代器卻沒有添加功能,所以我們使用其子接口ListIterator
        ListIterator lit = list.listIterator();
        while (lit.hasNext()) {
            String s = (String) lit.next();
            if ("world".equals(s)) {
                lit.add("javaee");
            }
        }

        // 方式2:集合遍歷元素,集合修改元素(普通for)
        for (int x = 0; x < list.size(); x++) {
            String s = (String) list.get(x);
            if ("world".equals(s)) {
                list.add("javaee");
            }
        }

        System.out.println("list:" + list);
    }
}

5. Map接口概述

map

5.1 Map接口概述

將鍵映射到值的對(duì)象,一個(gè)映射不能包含重復(fù)的鍵,每個(gè)鍵最多只能映射到一個(gè)值。其實(shí)Map集合中存儲(chǔ)的就是鍵值對(duì)。map集合中必須保證鍵的唯一性。

Map接口和Collection接口的不同

  • Map是雙列的,Collection是單列的
  • Map的鍵唯一,Collection的子體系Set是唯一的
  • Map集合的數(shù)據(jù)結(jié)構(gòu)值針對(duì)鍵有效,跟值無關(guān)
  • Collection集合的數(shù)據(jù)結(jié)構(gòu)是針對(duì)元素有效

Map常用的子類:

  • Hashtable:內(nèi)部結(jié)構(gòu)是哈希表,是同步的。不允許null作為鍵,null作為值。
  • Properties:用來存儲(chǔ)鍵值對(duì)型的配置文件的信息,可以和IO技術(shù)相結(jié)合。
  • HashMap:內(nèi)部結(jié)構(gòu)式哈希表,不是同步的。允許null作為鍵,null作為值。
  • TreeMap:內(nèi)部結(jié)構(gòu)式二叉樹,不是同步的??梢詫?duì)Map結(jié)合中的鍵進(jìn)行排序。
  • HashSet實(shí)現(xiàn)Set接口,由哈希表(實(shí)際上是一個(gè)HashMap實(shí)例)支持。

5.2 Map集合遍歷

方式1:根據(jù)鍵找值。獲取所有鍵的集合,遍歷鍵的集合,獲取到每一個(gè)鍵,根據(jù)鍵找值。

package cn.itcast;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/*
 * Map集合的遍歷。
 * Map -- 夫妻對(duì)
 * 思路:
 *      A:把所有的丈夫給集中起來。
 *      B:遍歷丈夫的集合,獲取得到每一個(gè)丈夫。
 *      C:讓丈夫去找自己的妻子。
 * 
 * 轉(zhuǎn)換:
 *      A:獲取所有的鍵
 *      B:遍歷鍵的集合,獲取得到每一個(gè)鍵
 *      C:根據(jù)鍵去找值
 */
public class MapDemo {
    public static void main(String[] args) {
        // 創(chuàng)建集合對(duì)象
        Map<String, String> map = new HashMap<String, String>();

        // 創(chuàng)建元素并添加到集合
        map.put("楊過", "小龍女");
        map.put("郭靖", "黃蓉");
        map.put("楊康", "穆念慈");
        map.put("陳玄風(fēng)", "梅超風(fēng)");

        // 遍歷
        // 獲取所有的鍵
        Set<String> set = map.keySet();
        // 遍歷鍵的集合,獲取得到每一個(gè)鍵
        for (String key : set) {
            // 根據(jù)鍵去找值
            String value = map.get(key);
            System.out.println(key + "---" + value);
        }
    }
}

方式2:根據(jù)鍵值對(duì)對(duì)象找鍵和值。

  • 獲取所有鍵值對(duì)對(duì)象的集合
  • 遍歷鍵值對(duì)對(duì)象的集合,獲取到每一個(gè)鍵值對(duì)對(duì)象
  • 根據(jù)鍵值對(duì)對(duì)象找鍵和值
package cn.itcast;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/*
 * Map集合的遍歷。
 * Map -- 夫妻對(duì)
 * 
 * 思路:
 *      A:獲取所有結(jié)婚證的集合
 *      B:遍歷結(jié)婚證的集合,得到每一個(gè)結(jié)婚證
 *      C:根據(jù)結(jié)婚證獲取丈夫和妻子
 * 
 * 轉(zhuǎn)換:
 *      A:獲取所有鍵值對(duì)對(duì)象的集合
 *      B:遍歷鍵值對(duì)對(duì)象的集合,得到每一個(gè)鍵值對(duì)對(duì)象
 *      C:根據(jù)鍵值對(duì)對(duì)象獲取鍵和值
 * 
 * 這里面最麻煩的就是鍵值對(duì)對(duì)象如何表示呢?
 * 看看我們開始的一個(gè)方法:
 *      Set<Map.Entry<K,V>> entrySet():返回的是鍵值對(duì)對(duì)象的集合
 */
public class MapDemo {
    public static void main(String[] args) {
        // 創(chuàng)建集合對(duì)象
        Map<String, String> map = new HashMap<String, String>();

        // 創(chuàng)建元素并添加到集合
        map.put("楊過", "小龍女");
        map.put("郭靖", "黃蓉");
        map.put("楊康", "穆念慈");
        map.put("陳玄風(fēng)", "梅超風(fēng)");

        // 獲取所有鍵值對(duì)對(duì)象的集合
        Set<Map.Entry<String, String>> set = map.entrySet();
        // 遍歷鍵值對(duì)對(duì)象的集合,得到每一個(gè)鍵值對(duì)對(duì)象
        for (Map.Entry<String, String> me : set) {
            // 根據(jù)鍵值對(duì)對(duì)象獲取鍵和值
            String key = me.getKey();
            String value = me.getValue();
            System.out.println(key + "---" + value);
        }
    }
}

3、HashMap類概述

鍵是哈希表結(jié)構(gòu),可以保證鍵的唯一性

4、LinkedHashMap類概述

Map 接口的哈希表和鏈接列表實(shí)現(xiàn),具有可預(yù)知的迭代順序。

5、TreeMap類概述

鍵是紅黑樹結(jié)構(gòu),可以保證鍵的排序和唯一性,自然排序,比較器排序。

6、Map集合的應(yīng)用及擴(kuò)展

package cn.itcast;

import java.util.Scanner;
import java.util.Set;
import java.util.TreeMap;

/*
 * 需求 :"aababcabcdabcde",獲取字符串中每一個(gè)字母出現(xiàn)的次數(shù)要求結(jié)果:a(5)b(4)c(3)d(2)e(1)
 * 
 * 分析:
 *      A:定義一個(gè)字符串(可以改進(jìn)為鍵盤錄入)
 *      B:定義一個(gè)TreeMap集合
 *          鍵:Character
 *          值:Integer
 *      C:把字符串轉(zhuǎn)換為字符數(shù)組
 *      D:遍歷字符數(shù)組,得到每一個(gè)字符
 *      E:拿剛才得到的字符作為鍵到集合中去找值,看返回值
 *          是null:說明該鍵不存在,就把該字符作為鍵,1作為值存儲(chǔ)
 *          不是null:說明該鍵存在,就把值加1,然后重寫存儲(chǔ)該鍵和值
 *      F:定義字符串緩沖區(qū)變量
 *      G:遍歷集合,得到鍵和值,進(jìn)行按照要求拼接
 *      H:把字符串緩沖區(qū)轉(zhuǎn)換為字符串輸出
 * 
 * 錄入:linqingxia
 * 結(jié)果:result:a(1)g(1)i(3)l(1)n(2)q(1)x(1)
 */
public class TreeMapDemo {
    public static void main(String[] args) {
        // 定義一個(gè)字符串(可以改進(jìn)為鍵盤錄入)
        Scanner sc = new Scanner(System.in);
        System.out.println("請(qǐng)輸入一個(gè)字符串:");
        String line = sc.nextLine();

        // 定義一個(gè)TreeMap集合
        TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>();

        // 把字符串轉(zhuǎn)換為字符數(shù)組
        char[] chs = line.toCharArray();

        // 遍歷字符數(shù)組,得到每一個(gè)字符
        for (char ch : chs) {
            // 拿剛才得到的字符作為鍵到集合中去找值,看返回值
            Integer i = tm.get(ch);

            // 是null:說明該鍵不存在,就把該字符作為鍵,1作為值存儲(chǔ)
            if (i == null) {
                tm.put(ch, 1);
            } else {
                // 不是null:說明該鍵存在,就把值加1,然后重寫存儲(chǔ)該鍵和值
                i++;
                tm.put(ch, i);
            }
        }

        // 定義字符串緩沖區(qū)變量
        StringBuilder sb = new StringBuilder();

        // 遍歷集合,得到鍵和值,進(jìn)行按照要求拼接
        Set<Character> set = tm.keySet();
        for (Character key : set) {
            Integer value = tm.get(key);
            sb.append(key).append("(").append(value).append(")");
        }

        // 把字符串緩沖區(qū)轉(zhuǎn)換為字符串輸出
        String result = sb.toString();
        System.out.println("result:" + result);
    }
}

示例2:在很多項(xiàng)目中,應(yīng)用比較多的是一對(duì)多的映射關(guān)系,這就可以通過嵌套的形式將多個(gè)映射定義到一個(gè)大的集合中,并將大的集合分級(jí)處理,形成一個(gè)體系。

package cn.itcast;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

class Student {
    private String name;
    private int age;

    public Student() {
        super();
    }

    public Student(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;
    }

}
/*
 * 黑馬程序員
 *      bj  北京校區(qū)
 *          jc  基礎(chǔ)班
 *                  林青霞     27
 *                  風(fēng)清揚(yáng)     30
 *          jy  就業(yè)班 
 *                  趙雅芝     28
 *                  武鑫      29
 *      sh  上海校區(qū)
 *          jc  基礎(chǔ)班
 *                  郭美美     20
 *                  犀利哥     22
 *          jy  就業(yè)班 
 *                  羅玉鳳     21
 *                  馬征      23
 *      gz  廣州校區(qū)
 *          jc  基礎(chǔ)班
 *                  王力宏     30
 *                  李靜磊     32
 *          jy  就業(yè)班 
 *                  郎朗      31
 *                  柳巖      33
 *      xa  西安校區(qū)
 *          jc  基礎(chǔ)班
 *                  范冰冰     27
 *                  劉意      30
 *          jy  就業(yè)班 
 *                  李冰冰     28
 *                  張志豪     29
 */
public class HashMapDemo {
    public static void main(String[] args) {
        // 創(chuàng)建大集合
        HashMap<String, HashMap<String, ArrayList<Student>>> czbkMap = new HashMap<String, HashMap<String, ArrayList<Student>>>();

        // 北京校區(qū)數(shù)據(jù)
        HashMap<String, ArrayList<Student>> bjCzbkMap = new HashMap<String, ArrayList<Student>>();
        ArrayList<Student> array1 = new ArrayList<Student>();
        Student s1 = new Student("林青霞", 27);
        Student s2 = new Student("風(fēng)清揚(yáng)", 30);
        array1.add(s1);
        array1.add(s2);
        ArrayList<Student> array2 = new ArrayList<Student>();
        Student s3 = new Student("趙雅芝", 28);
        Student s4 = new Student("武鑫", 29);
        array2.add(s3);
        array2.add(s4);
        bjCzbkMap.put("基礎(chǔ)班", array1);
        bjCzbkMap.put("就業(yè)班", array2);
        czbkMap.put("北京校區(qū)", bjCzbkMap);

        // 西安校區(qū)數(shù)據(jù)
        HashMap<String, ArrayList<Student>> xaCzbkMap = new HashMap<String, ArrayList<Student>>();
        ArrayList<Student> array3 = new ArrayList<Student>();
        Student s5 = new Student("范冰冰", 27);
        Student s6 = new Student("劉意", 30);
        array3.add(s5);
        array3.add(s6);
        ArrayList<Student> array4 = new ArrayList<Student>();
        Student s7 = new Student("李冰冰", 28);
        Student s8 = new Student("張志豪", 29);
        array4.add(s7);
        array4.add(s8);
        xaCzbkMap.put("基礎(chǔ)班", array3);
        xaCzbkMap.put("就業(yè)班", array4);
        czbkMap.put("西安校區(qū)", xaCzbkMap);

        // 遍歷集合
        Set<String> czbkMapSet = czbkMap.keySet();
        for (String czbkMapKey : czbkMapSet) {
            System.out.println(czbkMapKey);
            HashMap<String, ArrayList<Student>> czbkMapValue = czbkMap
                    .get(czbkMapKey);
            Set<String> czbkMapValueSet = czbkMapValue.keySet();
            for (String czbkMapValueKey : czbkMapValueSet) {
                System.out.println("\t" + czbkMapValueKey);
                ArrayList<Student> czbkMapValueValue = czbkMapValue
                        .get(czbkMapValueKey);
                for (Student s : czbkMapValueValue) {
                    System.out.println("\t\t" + s.getName() + "---"
                            + s.getAge());
                }
            }
        }
    }
}

運(yùn)行結(jié)果:

6. 集合框架的綜合應(yīng)用

代碼示例:模擬斗地主洗牌和發(fā)牌

package cn.itcast_04;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;

/*
 * 思路:
 *      A:創(chuàng)建一個(gè)HashMap集合
 *      B:創(chuàng)建一個(gè)ArrayList集合
 *      C:創(chuàng)建花色數(shù)組和點(diǎn)數(shù)數(shù)組
 *      D:從0開始往HashMap里面存儲(chǔ)編號(hào),并存儲(chǔ)對(duì)應(yīng)的牌
 *        同時(shí)往ArrayList里面存儲(chǔ)編號(hào)即可。
 *      E:洗牌(洗的是編號(hào))
 *      F:發(fā)牌(發(fā)的也是編號(hào),為了保證編號(hào)是排序的,就創(chuàng)建TreeSet集合接收)
 *      G:看牌(遍歷TreeSet集合,獲取編號(hào),到HashMap集合找對(duì)應(yīng)的牌)
 */
public class PokerDemo {
    public static void main(String[] args) {
        // 創(chuàng)建一個(gè)HashMap集合
        HashMap<Integer, String> hm = new HashMap<Integer, String>();

        // 創(chuàng)建一個(gè)ArrayList集合
        ArrayList<Integer> array = new ArrayList<Integer>();

        // 創(chuàng)建花色數(shù)組和點(diǎn)數(shù)數(shù)組
        // 定義一個(gè)花色數(shù)組
        String[] colors = { "?", "?", "?", "?" };
        // 定義一個(gè)點(diǎn)數(shù)數(shù)組
        String[] numbers = { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q",
                "K", "A", "2", };

        // 從0開始往HashMap里面存儲(chǔ)編號(hào),并存儲(chǔ)對(duì)應(yīng)的牌,同時(shí)往ArrayList里面存儲(chǔ)編號(hào)即可。
        int index = 0;

        for (String number : numbers) {
            for (String color : colors) {
                String poker = color.concat(number);
                hm.put(index, poker);
                array.add(index);
                index++;
            }
        }
        hm.put(index, "小王");
        array.add(index);
        index++;
        hm.put(index, "大王");
        array.add(index);

        // 洗牌(洗的是編號(hào))
        Collections.shuffle(array);

        // 發(fā)牌(發(fā)的也是編號(hào),為了保證編號(hào)是排序的,就創(chuàng)建TreeSet集合接收)
        TreeSet<Integer> fengQingYang = new TreeSet<Integer>();
        TreeSet<Integer> linQingXia = new TreeSet<Integer>();
        TreeSet<Integer> liuYi = new TreeSet<Integer>();
        TreeSet<Integer> diPai = new TreeSet<Integer>();

        for (int x = 0; x < array.size(); x++) {
            if (x >= array.size() - 3) {
                diPai.add(array.get(x));
            } else if (x % 3 == 0) {
                fengQingYang.add(array.get(x));
            } else if (x % 3 == 1) {
                linQingXia.add(array.get(x));
            } else if (x % 3 == 2) {
                liuYi.add(array.get(x));
            }
        }

        // 看牌(遍歷TreeSet集合,獲取編號(hào),到HashMap集合找對(duì)應(yīng)的牌)
        lookPoker("風(fēng)清揚(yáng)", fengQingYang, hm);
        lookPoker("林青霞", linQingXia, hm);
        lookPoker("劉意", liuYi, hm);
        lookPoker("底牌", diPai, hm);
    }

    // 寫看牌的功能
    public static void lookPoker(String name, TreeSet<Integer> ts,
            HashMap<Integer, String> hm) {
        System.out.print(name + "的牌是:");
        for (Integer key : ts) {
            String value = hm.get(key);
            System.out.print(value + " ");
        }
        System.out.println();
    }
}

運(yùn)行結(jié)果:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 堅(jiān)持有空就寫點(diǎn)東西,算是回顧復(fù)習(xí)。 Java集合框架下大致可以分為如下五個(gè)部分:List列表、Set集合、Map映...
    鋒Plus閱讀 315評(píng)論 0 1
  • 一、集合框架的概述 1、概述: 1、簡(jiǎn)述:所謂集合,就是為方便對(duì)多個(gè)對(duì)象的操作,對(duì)對(duì)象進(jìn)行存儲(chǔ)。集合就是存儲(chǔ)對(duì)象最...
    玉圣閱讀 596評(píng)論 0 4
  • 概述 Java集合框架由Java類庫的一系列接口、抽象類以及具體實(shí)現(xiàn)類組成。我們這里所說的集合就是把一組對(duì)象組織到...
    absfree閱讀 1,412評(píng)論 0 10
  • Collection ├List │├LinkedList │├ArrayList │└Vector │└Stac...
    AndyZX閱讀 963評(píng)論 0 1
  • 1. Collections工具類 1.1 Collections類概述 針對(duì)集合操作 的工具類,里面的方法都是靜...
    JackChen1024閱讀 276評(píng)論 0 0

友情鏈接更多精彩內(nèi)容