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

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

1. 集合類(lèi)概述

1.1 為什么出現(xiàn)集合類(lèi)春锋?

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

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

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

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

2. Collection接口概述

Collection 層次結(jié)構(gòu)中的根接口悦析。Collection 表示一組對(duì)象寿桨,這些對(duì)象也稱(chēng)為 collection 的元素。一些 collection 允許有重復(fù)的元素强戴,而另一些則不允許亭螟。一些 collection 是有序的,而另一些則是無(wú)序的骑歹。

3. Collection接口成員方法

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

4.1 List接口概述

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

4.1.1 ArrayList類(lèi)概述

底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組也糊,查詢(xún)快,增刪慢羡宙,線(xiàn)程不安全,效率高掐隐。

4.1.2 Vector類(lèi)概述

底層數(shù)據(jù)結(jié)構(gòu)是數(shù)組狗热,查詢(xún)快,增刪慢虑省,線(xiàn)程安全匿刮,效率低。

4.1.3 Vector類(lèi)特有功能

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

4.1.4 LinkedList類(lèi)概述

底層數(shù)據(jù)結(jié)構(gòu)是鏈表探颈,查詢(xún)慢熟丸,增刪快,線(xiàn)程不安全伪节,效率高

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

代碼示例:使用LinkedList來(lái)模擬一個(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) {
        // 將指定元素插入此列表的開(kāi)頭
        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呀闻,無(wú)序。

哈希表確定元素是否相同

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

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

4.2.1 HashSet類(lèi)概述

  • 不保證 set 的迭代順序堤结,特別是它不保證該順序恒久不變唆迁。
  • HashSet如何保證元素唯一性
  • 底層數(shù)據(jù)結(jié)構(gòu)是哈希表(元素是鏈表的數(shù)組)
  • 哈希表依賴(lài)于哈希值存儲(chǔ)
  • 添加功能底層依賴(lài)兩個(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)底層依賴(lài):hashCode()和equals()方法瘾带。
 * 如果你認(rèn)為對(duì)象的成員變量值相同即為同一個(gè)對(duì)象的話(huà)鼠哥,你就應(yīng)該重寫(xiě)這兩個(gè)方法。 如何重寫(xiě)呢?不同擔(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類(lèi)概述

元素有序唯一,由鏈表保證元素有序允蚣,由哈希表保證元素唯一于颖。

4.3 TreeSet類(lèi)概述

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

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

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

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

  • 可以使用TreeSet集合第二種排序方式
    讓集合自身具備比較功能,定義一個(gè)類(lèi)實(shí)現(xiàn)Comparator接口询枚,覆蓋compare方法违帆。將該類(lèi)對(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來(lái)決定金蜀。 排序: A:自然排序(元素具備比較性)
 * 讓元素所屬的類(lèi)實(shí)現(xiàn)自然排序接口 Comparable B:比較器排序(集合具備比較性) 讓集合的構(gòu)造方法接收一個(gè)比較器接口的子類(lèi)對(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)類(lèi)的對(duì)象
        // 而匿名內(nèi)部類(lè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é)也不一樣尝胆。但是都具有共性?xún)?nèi)容: 判斷和取出。那么就可以將這些共性抽取护桦。那么這些內(nèi)部類(lèi)都符合一個(gè)規(guī)則(或者說(shuō)都抽取出來(lái)一個(gè)規(guī)則)含衔。該規(guī)則就是Iterator。通過(guò)一個(gè)對(duì)外提供的方法:iterator();二庵,來(lái)獲取集合的取出對(duì)象贪染。因?yàn)镃ollection中有iterator方法,所以每一個(gè)子類(lèi)集合對(duì)象都具備迭代器催享。

迭代的常見(jiàn)操作


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

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

解決方法:

A:迭代器迭代元素攀涵,迭代器修改铣耘。因?yàn)镮terator沒(méi)有添加功能,所以使用其子接口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;

/*
 * 問(wèn)題:有一個(gè)集合鳄乏,如下,請(qǐng)問(wèn)棘利,我想判斷里面有沒(méi)有"world"這個(gè)元素,如果有朽缴,我就添加一個(gè)"javaee"元素善玫,請(qǐng)寫(xiě)代碼實(shí)現(xiàn)。
 * 
 * ConcurrentModificationException:當(dāng)方法檢測(cè)到對(duì)象的并發(fā)修改,但不允許這種修改時(shí)茅郎,拋出此異常蜗元。 
 * 產(chǎn)生的原因:
 * 迭代器是依賴(lài)于集合而存在的,在判斷成功后系冗,集合的中新添加了元素奕扣,而迭代器卻不知道,所以就報(bào)錯(cuò)了掌敬,這個(gè)錯(cuò)叫并發(fā)修改異常惯豆。
 * 其實(shí)這個(gè)問(wèn)題描述的是:迭代器遍歷元素的時(shí)候,通過(guò)集合是不能修改元素的奔害。
 * 如何解決呢?
 * 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迭代器卻沒(méi)有添加功能雅潭,所以我們使用其子接口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ì)鍵有效顽染,跟值無(wú)關(guān)
  • Collection集合的數(shù)據(jù)結(jié)構(gòu)是針對(duì)元素有效

Map常用的子類(lèi):

  • Hashtable:內(nèi)部結(jié)構(gòu)是哈希表,是同步的轰绵。不允許null作為鍵粉寞,null作為值。
  • Properties:用來(lái)存儲(chǔ)鍵值對(duì)型的配置文件的信息左腔,可以和IO技術(shù)相結(jié)合唧垦。
  • HashMap:內(nèi)部結(jié)構(gòu)式哈希表,不是同步的液样。允許null作為鍵振亮,null作為值。
  • TreeMap:內(nèi)部結(jié)構(gòu)式二叉樹(shù)鞭莽,不是同步的坊秸。可以對(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:把所有的丈夫給集中起來(lái)硝桩。
 *      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("楊過(guò)", "小龍女");
        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ì)象如何表示呢?
 * 看看我們開(kāi)始的一個(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("楊過(guò)", "小龍女");
        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類(lèi)概述

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

4痴晦、LinkedHashMap類(lèi)概述

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

5誊酌、TreeMap類(lèi)概述

鍵是紅黑樹(shù)結(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)為鍵盤(pán)錄入)
 *      B:定義一個(gè)TreeMap集合
 *          鍵:Character
 *          值:Integer
 *      C:把字符串轉(zhuǎn)換為字符數(shù)組
 *      D:遍歷字符數(shù)組箱锐,得到每一個(gè)字符
 *      E:拿剛才得到的字符作為鍵到集合中去找值比勉,看返回值
 *          是null:說(shuō)明該鍵不存在,就把該字符作為鍵驹止,1作為值存儲(chǔ)
 *          不是null:說(shuō)明該鍵存在浩聋,就把值加1,然后重寫(xiě)存儲(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)為鍵盤(pá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:說(shuō)明該鍵不存在坊夫,就把該字符作為鍵毙替,1作為值存儲(chǔ)
            if (i == null) {
                tm.put(ch, 1);
            } else {
                // 不是null:說(shuō)明該鍵存在,就把值加1践樱,然后重寫(xiě)存儲(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)系,這就可以通過(guò)嵌套的形式將多個(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開(kāi)始往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開(kāi)始往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);
    }

    // 寫(xiě)看牌的功能
    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)系作者
  • 序言:七十年代末驯鳖,一起剝皮案震驚了整個(gè)濱河市闲询,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌浅辙,老刑警劉巖扭弧,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異摔握,居然都是意外死亡寄狼,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)氨淌,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)泊愧,“玉大人,你說(shuō)我怎么就攤上這事盛正∩驹郏” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵豪筝,是天一觀的道長(zhǎng)痰滋。 經(jīng)常有香客問(wèn)我摘能,道長(zhǎng),這世上最難降的妖魔是什么敲街? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任团搞,我火速辦了婚禮,結(jié)果婚禮上多艇,老公的妹妹穿的比我還像新娘逻恐。我一直安慰自己,他們只是感情好峻黍,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布复隆。 她就那樣靜靜地躺著,像睡著了一般姆涩。 火紅的嫁衣襯著肌膚如雪挽拂。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,258評(píng)論 1 300
  • 那天骨饿,我揣著相機(jī)與錄音亏栈,去河邊找鬼。 笑死样刷,一個(gè)胖子當(dāng)著我的面吹牛仑扑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播置鼻,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼镇饮,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了箕母?” 一聲冷哼從身側(cè)響起储藐,我...
    開(kāi)封第一講書(shū)人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎嘶是,沒(méi)想到半個(gè)月后钙勃,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡聂喇,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年辖源,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片希太。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡克饶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出誊辉,到底是詐尸還是另有隱情矾湃,我是刑警寧澤,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布堕澄,位于F島的核電站邀跃,受9級(jí)特大地震影響霉咨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拍屑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一途戒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧僵驰,春花似錦棺滞、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)枉证。三九已至矮男,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間室谚,已是汗流浹背毡鉴。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留秒赤,地道東北人猪瞬。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像入篮,于是被迫代替她去往敵國(guó)和親陈瘦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

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