Java復(fù)習(xí)之集合框架


俗話說(shuō):溫故而知新。想想學(xué)過(guò)的知識(shí)尉尾,就算是以前學(xué)得很不錯(cuò)爆阶,久不用了,就會(huì)忘記沙咏,所以溫習(xí)一下以前學(xué)習(xí)的知識(shí)我認(rèn)為是非常有必要的辨图。而本篇文件溫習(xí)的是 Java基礎(chǔ)中的集合框架。

  • 為什么會(huì)有集合框架芭碍?

    • 平時(shí)我們用數(shù)組存儲(chǔ)一些基本的數(shù)據(jù)類型徒役,或者是引用數(shù)據(jù)類型,但是數(shù)組的長(zhǎng)度是固定的窖壕,當(dāng)添加的元素超過(guò)了數(shù)組的長(zhǎng)度時(shí),需要對(duì)數(shù)組進(jìn)行重新的定義杉女,這樣就會(huì)顯得寫程序太麻煩瞻讽,所以Java內(nèi)部為了我們方便,就提供了集合類熏挎,能存儲(chǔ)任意對(duì)象速勇,長(zhǎng)度是可以改變的,隨著元素的增加而增加坎拐,隨著元素的減少而減少烦磁。
    • 數(shù)組可以存儲(chǔ)基本數(shù)據(jù)類型,也可以存儲(chǔ)引用數(shù)據(jù)類型哼勇,基本數(shù)據(jù)類型存儲(chǔ)的是值都伪,引用數(shù)據(jù)類型存儲(chǔ)的是地址,而集合只能存儲(chǔ)引用數(shù)據(jù)類型(也就是對(duì)象)积担,其實(shí)集合中也可以存儲(chǔ)基本數(shù)據(jù)類型陨晶,但是在存儲(chǔ)的時(shí)候會(huì)自動(dòng)裝箱變成對(duì)象。
    • 有了集合不意味著我們要拋棄數(shù)組帝璧,如果需要存儲(chǔ)的元素個(gè)數(shù)是固定的先誉,我們可以使用數(shù)組,而當(dāng)存儲(chǔ)的元素不固定的烁,我們使用集合褐耳。
  • 集合的種類

    • 集合分為單列集合和雙列集合。單列集合的根接口為Collection,雙列結(jié)合的根接口為Map,兩種集合都有基于哈希算法的集合類(HashMap和HashSet)渴庆,現(xiàn)在我們可能會(huì)有疑問(wèn)铃芦,到底是雙列集合基于單列集合還是單列集合基于雙列集合呢买雾,下面我們來(lái)看往集合HashMap和HashSet添加元素的源碼:
/*
*HashMap的put 方法 
*/
 public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
                   boolean evict) {
        Node<K,V>[] tab; Node<K,V> p; int n, i;
        if ((tab = table) == null || (n = tab.length) == 0)
            n = (tab = resize()).length;
        if ((p = tab[i = (n - 1) & hash]) == null)
            tab[i] = newNode(hash, key, value, null);
        else {
            Node<K,V> e; K k;
            if (p.hash == hash &&
                ((k = p.key) == key || (key != null && key.equals(k))))
                e = p;
            else if (p instanceof TreeNode)
                e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
            else {
                for (int binCount = 0; ; ++binCount) {
                    if ((e = p.next) == null) {
                        p.next = newNode(hash, key, value, null);
                        if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
                            treeifyBin(tab, hash);
                        break;
                    }
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        break;
                    p = e;
                }
            }
            if (e != null) { // existing mapping for key
                V oldValue = e.value;
                if (!onlyIfAbsent || oldValue == null)
                    e.value = value;
                afterNodeAccess(e);
                return oldValue;
            }
        }
        ++modCount;
        if (++size > threshold)
            resize();
        afterNodeInsertion(evict);
        return null;
    }

/*
* HashSet  的add 方法
*/
public boolean add(E e) {
        return map.put(e, PRESENT)==null;
    }
// PRESENT是一個(gè)Object 對(duì)象
 private static final Object PRESENT = new Object();
  • 由上源碼,我們可以看出杨帽,雙列集合的put方法源碼中并沒(méi)有出現(xiàn)add方法漓穿,而單列集合的add源碼只能怪出現(xiàn)了put;我們可以知道單列集合是基于雙列集合實(shí)現(xiàn)的注盈。其實(shí)道理很簡(jiǎn)單晃危,單列集合每次添加元素,只要添加key就可以老客,而key也是雙列集合元素的唯一標(biāo)識(shí)僚饭,而其值value則由一個(gè)Object對(duì)象代替并且隱藏,每次加入胧砰,輸出元素都是隱藏單列結(jié)合的這個(gè)值鳍鸵, 底層基于雙列集合,隱藏一列是很好實(shí)現(xiàn)的尉间,而如果是單列集合要變成雙列集合估計(jì)就會(huì)有很大的難度偿乖,就好比魔術(shù)師變魔術(shù),魔術(shù)師變東西前肯定事先準(zhǔn)備好要變的東西哲嘲,只是將其隱藏贪薪,但是如果魔術(shù)師變魔術(shù)是真的從無(wú)到有,那我估計(jì)他就是神仙了眠副,想要什么就變出來(lái)什么便是画切。

單列集合

  • 首先我們看單列結(jié)合的繼承圖,單列集合的根接口是Collection,而List的實(shí)現(xiàn)類為ArrayList囱怕、LinkedList霍弹、Vector,Set接口的實(shí)現(xiàn)類是HashSet和TreeSet娃弓。
集合框架 單列集合.jpg
  • 其次我們來(lái)看看各個(gè)集合的功能
List集合的特有功能概述
    * void add(int index,E element) //集合中添加元素
    * E remove(int index) //刪除集合中index位置上的元素
    * E get(int index)  //獲取集合中index位置上的元素
    * E set(int index,E element) 將index位置上的元素替換成 element

Vector類特有功能
    * public void addElement(E obj)  添加元素
    * public E elementAt(int index)  //獲取元素
    * public Enumeration elements()  //獲取元素的枚舉(迭代遍歷的時(shí)候用到)

LinkedList類特有功能
    * public void addFirst(E e)及addLast(E e)  //集合頭添加元素或者集合尾添加元素
    * public E getFirst()及getLast() //獲取頭元素 獲取尾元素
    * public E removeFirst()及public E removeLast() //刪除頭元素刪除尾元素
    * public E get(int index);//獲取index元素
根據(jù)上述LinkedList的功能典格,我們可以模擬棧獲取隊(duì)列的數(shù)據(jù)結(jié)構(gòu),棧是先進(jìn)后出忘闻,隊(duì)列為先進(jìn)先出钝计。

/**
 * 模擬的棧對(duì)象
 * @author 毛麒添
 * 底層還是使用LinkedList實(shí)現(xiàn)
 * 如果實(shí)現(xiàn)隊(duì)列只需要將出棧變?yōu)?removeFirst 
 */
public class Stack {

    private LinkedList linklist=new LinkedList();
    
    /**
     * 進(jìn)棧的方法
     * @param obj
     */
    public void in(Object obj){
        linklist.addLast(obj);
    }
    
    /**
     * 出棧
     */
    public Object out(){
        return linklist.removeLast();
    }
    /**
     * 棧是否為空
     * @return
     */
    public boolean isEmpty(){
        return linklist.isEmpty();
    }
}


//集合的三種迭代(遍歷集合)刪除
ArrayList<String> list=new ArrayList();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("world");
//1,普通for循環(huán)刪除元素
for(int i=0;i<list,size();i++){//刪除元素b
     if("b".equals(list.get(i))){
        list.remove(i--);// i-- 當(dāng)集合中有重復(fù)元素的時(shí)候保證要?jiǎng)h除的重復(fù)元素被刪除
  }
}
//2.使用迭代器遍歷集合
Iterator<String> it=list.iterator();
while(it.hasNext){
   if("b".equals(it.next())){
     it.remove();//這里必須使用迭代器的刪除方法齐佳,而不能使用集合的刪除方法私恬,否則會(huì)出現(xiàn)并發(fā)修改異常(ConcurrentModificationException)
  }
}

//使用增強(qiáng)for循環(huán)來(lái)進(jìn)行刪除
for (String str:list){
     if("b".equals(str)){
       list.remove("b");//增強(qiáng)for循環(huán)底層依賴的是迭代器,而這里刪除使用的依舊是集合的刪除方法炼吴,同理肯定是會(huì)出現(xiàn)并發(fā)修改異常(ConcurrentModificationException)本鸣,所以增強(qiáng)for循環(huán)一直能用來(lái)遍歷集合,不能對(duì)集合的元素進(jìn)行刪除硅蹦。
  }
}
  • 接下里我們看Set集合荣德,我們知道Set 集合存儲(chǔ)無(wú)序闷煤,無(wú)索引,不可以存儲(chǔ)重復(fù)的對(duì)象涮瞻;我們使用Set集合都是需要去掉重復(fù)元素的, 如果在存儲(chǔ)的時(shí)候逐個(gè)equals()比較, 效率較低,哈希算法提高了去重復(fù)的效率, 降低了使用equals()方法的次數(shù)鲤拿,其中HashSet底層基于哈希算法,當(dāng)HashSet調(diào)用add方法存儲(chǔ)對(duì)象署咽,先調(diào)用對(duì)象的hashCode()方法得到一個(gè)哈希值, 然后在集合中查找是否有哈希值相同的對(duì)象近顷,如果沒(méi)有哈希值相同的對(duì)象就直接存入集合,如果有哈希值相同的對(duì)象, 就和哈希值相同的對(duì)象逐個(gè)進(jìn)行equals()比較,比較結(jié)果為false就存入, true則不存宁否。下面給出HashSet存儲(chǔ)自定義對(duì)象的一個(gè)例子窒升,自定義對(duì)象需要重寫hashCode()和equals()方法。
/**
 * 自定義對(duì)象
 * @author 毛麒添
 * HashSet 使用的bean  重寫了equals和HashCode方法
 */
public class Person1 {
    private String name;
    private int age;
    public Person1() {
        super();
        // TODO Auto-generated constructor stub
    }
    public Person1(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 "Person1 [name=" + name + ", age=" + age + "]";
    }
    
    //使HashSet存儲(chǔ)元素唯一
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        System.out.println("equals調(diào)用了");
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Person1 other = (Person1) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }   
}

public class Demo1_Hashset {

    public static void main(String[] args) {
        HashSet<Person1> hs=new HashSet<Person1>();
        hs.add(new Person1("張三", 23));
        hs.add(new Person1("張三", 23));
        hs.add(new Person1("李四", 24));
        hs.add(new Person1("李四", 24));
        hs.add(new Person1("李四", 24));
        hs.add(new Person1("李四", 24));
        System.out.println(hs);
    }

運(yùn)行結(jié)果如圖慕匠,達(dá)到了不存儲(chǔ)重復(fù)自定義對(duì)象的目的饱须。其實(shí)HashSet的下面還有一個(gè)LinkedHashSet,底層是鏈表實(shí)現(xiàn)的,是set中唯一一個(gè)能保證怎么存就怎么取的集合對(duì)象,是HashSet的子類台谊,保證元素唯一蓉媳,與HashSet原理一樣,這里就不多說(shuō)了。

HashSet 例子運(yùn)行結(jié)果截圖.png
  • 最后是TreeSet集合青伤,該集合是用來(lái)進(jìn)行排序的督怜,同樣也可以保證元素的唯一,可以指定一個(gè)順序, 對(duì)象存入之后會(huì)按照指定的順序排列狠角。
    指定排序有兩種實(shí)現(xiàn):
    • Comparable:集合加入自定義對(duì)象的時(shí)候,自定義對(duì)象需要實(shí)現(xiàn)Comparable接口蚪腋,
      • 實(shí)現(xiàn)接口的抽象方法中返回0丰歌,則集合中只有一個(gè)元素
      • 返回正數(shù),則集合中怎么存則怎么取屉凯,
      • 返回負(fù)數(shù)立帖,集合倒序存儲(chǔ)
    • Comparator(比較器):
      • 創(chuàng)建TreeSet的時(shí)候可以制定 一個(gè)Comparator
      • 如果傳入了Comparator的子類對(duì)象, 那么TreeSet就會(huì)按照比較器中的順序排序
      • add()方法內(nèi)部會(huì)自動(dòng)調(diào)用Comparator接口中compare()方法排序
      • 調(diào)用的對(duì)象是compare方法的第一個(gè)參數(shù),集合中的對(duì)象是compare方法的第二個(gè)參數(shù)
    • 原理:
      • TreeSet底層二叉排序樹
      • 返回小的數(shù)字存儲(chǔ)在樹的左邊(負(fù)數(shù)),大的存儲(chǔ)在右邊(正數(shù))悠砚,相等則不存(等于0)
      • 在TreeSet集合中如何存取元素取決于compareTo()方法的返回值

下面來(lái)看例子:

/**
 * 自定義對(duì)象 用于TreeSet
 * @author 毛麒添
 *
 */
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 String toString() {
        return "Person [name=" + name + ", age=" + age + "]";
    }
    
    @Override
    public boolean equals(Object obj) {
        Person p=(Person) obj;
        return this.name.equals(p.name)&&this.age==p.age;
    }
    
    @Override
    public int hashCode() {
        // TODO Auto-generated method stub
        return 1;
    }
    
    /*//按照年齡進(jìn)行排序(TreeSet)
    @Override
    public int compareTo(Person o) {
        int number=this.age-o.age;//年齡是比較的主要條件
        //當(dāng)年齡一樣的時(shí)候比較名字來(lái)確定排序
        return number==0?this.name.compareTo(o.name):number;
    }*/
    
    //按照姓名進(jìn)行排序(TreeSet)
        @Override
        public int compareTo(Person o) {
            int number=this.name.compareTo(o.name);//姓名是比較的主要條件
            //當(dāng)姓名一樣的時(shí)候比年齡來(lái)確定排序
            return number==0?this.age- o.age:number;
        }
        
        //按照姓名長(zhǎng)度進(jìn)行排序(TreeSet)
                /*@Override
                public int compareTo(Person o) {
                    int length=this.name.length()-o.name.length();//姓名長(zhǎng)度比較的次要條件
                    int number=length==0?this.name.compareTo(o.name):length;//姓名是比較的次要條件
                    //比年齡也是次要條件
                    return number==0?this.age- o.age:number;
                }*/
}

/**
 * 
 * @author 毛麒添
 * TreeSet集合
 * 集合加入自定義對(duì)象的時(shí)候晓勇,自定義對(duì)象需要實(shí)現(xiàn)Comparable接口,
 * 實(shí)現(xiàn)接口的抽象方法中返回0灌旧,則集合中只有一個(gè)元素
 * 返回正數(shù)绑咱,則集合中怎么存則怎么取,
 * 返回負(fù)數(shù)枢泰,集合倒序存儲(chǔ)
 * 
 * 將字符按照長(zhǎng)度來(lái)進(jìn)行排序在TreeSet中,需要使用有比較的構(gòu)造方法進(jìn)行比較描融。
 */
public class Demo_TreeSet {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        demo1();//整數(shù)存取排序
        demo2();//自定義對(duì)象排序
        
        //將字符按照長(zhǎng)度來(lái)進(jìn)行排序在TreeSet中
        TreeSet<String> strLenset=new TreeSet<String>(new compareByLen());
        strLenset.add("aaaaa");
        strLenset.add("lol");
        strLenset.add("wrc");
        strLenset.add("wc");
        strLenset.add("b");
        strLenset.add("wnnnnnnnnnnn");
        
        System.out.println(strLenset);
    }

    private static void demo2() {
        TreeSet<Person> ptreeSet=new TreeSet<Person>();
        
        ptreeSet.add(new Person("李四",12));
        ptreeSet.add(new Person("李四",16));
        ptreeSet.add(new Person("李青",16));
        ptreeSet.add(new Person("王五",19));
        ptreeSet.add(new Person("趙六",22));
        
        System.out.println(ptreeSet);
    }

    private static void demo1() {
        TreeSet< Integer> treeSet=new TreeSet<Integer>();
        treeSet.add(1);
        treeSet.add(1);
        treeSet.add(1);
        treeSet.add(3);
        treeSet.add(3);
        treeSet.add(3);
        treeSet.add(2);
        treeSet.add(2);
        treeSet.add(2);
        
        System.out.println(treeSet);
    }

}

//TreeSet 構(gòu)造器,實(shí)現(xiàn)compare對(duì)需要存儲(chǔ)的字符串進(jìn)行比較
class compareByLen implements Comparator<String>{

    //按照字符串的長(zhǎng)度進(jìn)行比較衡蚂,該方法的返回值和繼承Comparable的compareTo方法返回值同理窿克。
    @Override
    public int compare(String o1, String o2) {
        int num=o1.length()-o2.length();//以長(zhǎng)度為主要條件
        return num==0?o1.compareTo(o2):num;//內(nèi)容為次要條件
    }
    
}


  • 下面是運(yùn)行截圖骏庸,其中compareTo的實(shí)現(xiàn)方法對(duì)幾種條件排序進(jìn)行了實(shí)現(xiàn),具體可以查看Person自定義類中的實(shí)現(xiàn)年叮。
TreeSet 例子運(yùn)行截圖.png

單列集合復(fù)習(xí)就到這里吧具被。


雙列集合

  • 同樣的,在復(fù)習(xí)雙列結(jié)合之前我們先看看雙列集合的繼承圖只损。
集合框架 雙列集合.jpg
  • Map集合的功能梳理:

    • 添加功能
      • V put(K key,V value):添加元素一姿。
      • 如果鍵是第一次存儲(chǔ),就直接存儲(chǔ)元素改执,返回null
      • 如果鍵不是第一次存在啸蜜,就用值把以前的值替換掉,返回以前的值
    • 刪除功能
      • void clear():移除所有的鍵值對(duì)元素
      • V remove(Object key):根據(jù)鍵刪除鍵值對(duì)元素辈挂,并把值返回
    • 判斷功能
      • boolean containsKey(Object key):判斷集合是否包含指定的鍵
      • boolean containsValue(Object value):判斷集合是否包含指定的值
      • boolean isEmpty():判斷集合是否為空
    • 獲取功能
      • Set<Map.Entry<K,V>> entrySet():
      • V get(Object key):根據(jù)鍵獲取值
      • Set<K> keySet():獲取集合中所有鍵的集合
      • Collection<V> values():獲取集合中所有值的集合
    • 長(zhǎng)度功能
      • int size():返回集合中的鍵值對(duì)的個(gè)數(shù)
  • Map類集合也有三種遍歷方式:

    • 使用迭代器進(jìn)行遍歷
    • 使用增強(qiáng)For循環(huán)來(lái)進(jìn)行遍歷
    • 使用Map.Entry來(lái)遍歷集合中的元素
  • 下面我們來(lái)看看如何實(shí)現(xiàn)上面三種遍歷方式

/**
 * 
 * @author 毛麒添
 * Map 集合的遍歷
 */
public class Demo {

    public static void main(String[] args) {
        Map<String ,Integer> map=new HashMap<String, Integer>();
        map.put("張三", 18);
        map.put("李四", 19);
        map.put("王五", 20);
        map.put("趙六", 21);
        
        //使用迭代器進(jìn)行遍歷
        /*Set<String> keySet = map.keySet();//獲取所有key的集合
        Iterator<String> iterator = keySet.iterator();
        while(iterator.hasNext()){
            String key = iterator.next();
            Integer i=map.get(key);
            System.out.println(i);
        }*/
        //使用增強(qiáng)For循環(huán)來(lái)進(jìn)行遍歷
        for (String key :map.keySet()) {
            Integer integer = map.get(key);
            System.out.println(integer);
        }
/*---------------------------使用Map.Entry來(lái)遍歷集合中的元素--------------------------*/
        Set<Map.Entry<String,Integer>> en=map.entrySet();////獲取所有的鍵值對(duì)象的集合
        /*//使用迭代器來(lái)遍歷
        Iterator<Entry<String, Integer>> iterator = en.iterator();
        while(iterator.hasNext()){
            Entry<String, Integer> e=iterator.next();//獲取鍵值對(duì)對(duì)象
            String key = e.getKey();//根據(jù)鍵值對(duì)對(duì)象獲取鍵
            Integer value = e.getValue();//根據(jù)鍵值對(duì)對(duì)象獲取值
            System.out.print(key);
            System.out.println(value);
        }*/
        //使用增強(qiáng)for循環(huán)來(lái)遍歷
        for (Entry<String, Integer> entry : en) {
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.print(key);
            System.out.println(value);
        }
/*---------------------------使用Map.Entry來(lái)遍歷集合中的元素--------------------------*/
    }
}
  • LinkedHashMap與LinkedHashSet一樣衬横,怎么存怎么取,保證元素唯一(key 是唯一判定值),由于保證元素唯一终蒂,其性能肯定會(huì)低一些蜂林,這里就不細(xì)說(shuō)了。

  • TreeMap是雙列集合拇泣,其實(shí)他和TreeSet是很像的噪叙,但是雙列集合的鍵是唯一標(biāo)識(shí),所以TreeMap排序的是每個(gè)元素的鍵霉翔。對(duì)于存儲(chǔ)自定義對(duì)象排序睁蕾,它也有Comparable和Comparator,下面我們來(lái)看例子

/**
 * 
 * @author 毛麒添
 * TreeMap
 *  通TreeSet 原理债朵,存取自定義對(duì)象也需要繼承Comparable結(jié)構(gòu)子眶,
 *  或者實(shí)現(xiàn)比較器Comparator
 */
public class Demo6_TreeMap {

    public static void main(String[] args) {
        TreeMap<Student, String> tm=new TreeMap<Student, String>(new Comparator<Student>() {

            @Override
            public int compare(Student s1, Student s2) {
                int num=s1.getName().compareTo(s2.getName());//以姓名作為主要比較條件
                return num==0?s1.getAge()-s2.getAge():num;
            }
        });
        tm.put(new Student("張三",13),"杭州");
        tm.put(new Student("張三",14), "賀州");
        tm.put(new Student("王五",15), "廣州");
        tm.put(new Student("趙六",16), "深圳");
        
        System.out.println(tm);
    }

}

/**
 * 自定義對(duì)象
 * @author 毛麒添
 * HashMap 存儲(chǔ)對(duì)象 與 HashSet 同理  需要重寫 hashcode 和equals 方法 
 * TreeMap 實(shí)現(xiàn) Comparable接口
 */
public class Student implements Comparable<Student>{

    private int age;
    private String name;
    
    public Student(){
        super();
    }
    public Student(String name,int age){
        this.name=name;
        this.age=age;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    
    
    @Override
    public String toString() {
        return "Student [age=" + age + ", name=" + name + "]";
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + age;
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Student other = (Student) obj;
        if (age != other.age)
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        return true;
    }
    @Override
    public int compareTo(Student o) {
        int num =this.age-o.age;//以年齡為主要條件
        return num==0?this.name.compareTo(o.name):num;//姓名作為次要條件
    }   
}

到這里,Java集合框架的復(fù)習(xí)基本完成序芦,最后來(lái)一個(gè)斗地主的例子對(duì)集合框架做一個(gè)綜合應(yīng)用臭杰,只是實(shí)現(xiàn)斗地主洗牌和發(fā)牌,至于怎么打牌谚中,邏輯復(fù)雜渴杆,這里不做實(shí)現(xiàn)。

/**
 * 
 * @author 毛麒添
 * 模擬斗地主洗牌和發(fā)牌宪塔,牌排序
 * 買一副撲克
 * 洗牌
 * 發(fā)牌
 * 看牌
 */
public class Doudizhu_progress {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //構(gòu)造一副撲克牌
        String[] number={"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
        String[]color={"黑桃","紅桃","梅花","方塊"};
        HashMap<Integer, String> pokerMap=new HashMap<Integer, String>();//存放牌的map
        ArrayList<Integer> list=new ArrayList<Integer>();//存放牌的索引
        int index=0; //索引
        for (String s1 : number) {
            for (String s2 : color) {
                pokerMap.put(index,s2.concat(s1));
                list.add(index);
                index++;
            
            }
        }
        //加入大小王
        pokerMap.put(index,"小王");
        list.add(index);
        index++;
        pokerMap.put(index,"大王");
        list.add(index);
        
        //洗牌
        Collections.shuffle(list);
        //System.out.println(list);
       
        //發(fā)牌磁奖,3個(gè)人玩 加上底牌3張 使用TreeSet 來(lái)存放索引,并自動(dòng)對(duì)索引排好序
        TreeSet<Integer> mao=new TreeSet<Integer>();
        TreeSet<Integer> li=new TreeSet<Integer>();
        TreeSet<Integer> huang=new TreeSet<Integer>();
        TreeSet<Integer> dipai=new TreeSet<Integer>();
        
        for(int i=0;i<list.size();i++){
            if(i>=list.size()-3){//最后三張牌蝌麸,作為底牌
               dipai.add(list.get(i));  
            }else if(i%3==0){
                mao.add(list.get(i));
            }else if(i%3==1){
                li.add(list.get(i));
            }else {
                huang.add(list.get(i));
            }
        }
        
        //看牌
        lookPoker(pokerMap,mao,"mao");
        lookPoker(pokerMap,li,"li");
        lookPoker(pokerMap,huang,"huang");
        lookPoker(pokerMap,dipai,"底牌");
    }

    /**
     * 看牌的方法
     * @param pokerMap 存放牌的map
     * @param mao  該玩家的牌的索引集合
     * @param name 玩家名字
     */
    private static void lookPoker(HashMap<Integer, String> pokerMap,
            TreeSet<Integer> mao, String name) {
        if(name.equals("底牌")){
            System.out.print("地主"+name+"的牌是:");
        }else{
            System.out.print("玩家"+name+"的牌是:");
        }
        for (Integer integer : mao) {
            System.out.print(pokerMap.get(integer)+" ");
        }
        
        System.out.println();
        
    }

}

運(yùn)行截圖:

斗地主程序運(yùn)行截圖.png

寫在最后:
如果你看到這里点寥,估計(jì)你也溫故知新了吧,那就這樣吧来吩,這篇又臭又長(zhǎng)的文章就到這里啦敢辩。文章中如果有錯(cuò)誤蔽莱,請(qǐng)大家給我提出來(lái),大家一起學(xué)習(xí)進(jìn)步戚长,如果覺(jué)得我的文章給予你幫助盗冷,也請(qǐng)給我一個(gè)喜歡。

本系列文章:
Java復(fù)習(xí)之集合框架
Java復(fù)習(xí)之IO流(上)
Java復(fù)習(xí)之IO流(下)
Java 復(fù)習(xí)之多線程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末同廉,一起剝皮案震驚了整個(gè)濱河市仪糖,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌迫肖,老刑警劉巖锅劝,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異蟆湖,居然都是意外死亡故爵,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門隅津,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)诬垂,“玉大人,你說(shuō)我怎么就攤上這事伦仍〗峋剑” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵充蓝,是天一觀的道長(zhǎng)隧枫。 經(jīng)常有香客問(wèn)我,道長(zhǎng)谓苟,這世上最難降的妖魔是什么悠垛? 我笑而不...
    開(kāi)封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮娜谊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘斤讥。我一直安慰自己纱皆,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布芭商。 她就那樣靜靜地躺著派草,像睡著了一般。 火紅的嫁衣襯著肌膚如雪铛楣。 梳的紋絲不亂的頭發(fā)上近迁,一...
    開(kāi)封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音簸州,去河邊找鬼鉴竭。 笑死歧譬,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的搏存。 我是一名探鬼主播瑰步,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼璧眠!你這毒婦竟也來(lái)了缩焦?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤责静,失蹤者是張志新(化名)和其女友劉穎袁滥,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體灾螃,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡题翻,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了睦焕。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片藐握。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖垃喊,靈堂內(nèi)的尸體忽然破棺而出猾普,到底是詐尸還是另有隱情,我是刑警寧澤本谜,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布初家,位于F島的核電站,受9級(jí)特大地震影響乌助,放射性物質(zhì)發(fā)生泄漏溜在。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一他托、第九天 我趴在偏房一處隱蔽的房頂上張望掖肋。 院中可真熱鬧,春花似錦赏参、人聲如沸志笼。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)纫溃。三九已至,卻和暖如春韧掩,著一層夾襖步出監(jiān)牢的瞬間紊浩,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留坊谁,地道東北人费彼。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像呜袁,于是被迫代替她去往敵國(guó)和親敌买。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法阶界,類相關(guān)的語(yǔ)法虹钮,內(nèi)部類的語(yǔ)法,繼承相關(guān)的語(yǔ)法膘融,異常的語(yǔ)法芙粱,線程的語(yǔ)...
    子非魚_t_閱讀 31,587評(píng)論 18 399
  • 一、集合框架的概述 1氧映、概述: 1春畔、簡(jiǎn)述:所謂集合,就是為方便對(duì)多個(gè)對(duì)象的操作岛都,對(duì)對(duì)象進(jìn)行存儲(chǔ)律姨。集合就是存儲(chǔ)對(duì)象最...
    玉圣閱讀 508評(píng)論 0 4
  • 上一篇文章介紹了Set集合的通用知識(shí)。Set集合中包含了三個(gè)比較重要的實(shí)現(xiàn)類:HashSet臼疫、TreeSet和En...
    Ruheng閱讀 15,613評(píng)論 3 57
  • 人的時(shí)間精力是有限的择份,大腦的運(yùn)作模式也是由基因進(jìn)化決定的能省就省,因?yàn)閺纳砩洗竽X維持日常的工作需要消耗大量的能量...
    塵世知行者閱讀 487評(píng)論 0 0
  • 為你我用了半年的積蓄烫堤, 漂洋過(guò)海的來(lái)看你荣赶, 為了這次相聚, 我連見(jiàn)面時(shí)的呼吸都曾反復(fù)練習(xí)鸽斟。 身邊有一部分朋友是異地...
    喜歡木子閱讀 334評(píng)論 0 0