Java基础:集合框架

Java类中集合的关系图

1. 集合类概述

1.1 为什么出现集合类?

面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,Java就提供了集合类。

1.2 数组和集合类同是容器,有何不同?

1.3 集合类的特点

集合只用于存储对象,集合长度是可变的,集合可以存储不同类型的对象。

2. Collection接口概述

Collection 层次结构中的根接口。Collection 表示一组对象,这些对象也称为 collection 的元素。一些 collection 允许有重复的元素,而另一些则不允许。一些 collection 是有序的,而另一些则是无序的。

3. Collection接口成员方法

4. Collection实现类

4.1 List接口概述

有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。与 set 不同,列表通常允许重复的元素。

4.1.1 ArrayList类概述

底层数据结构是数组,查询快,增删慢,线程不安全,效率高。

4.1.2 Vector类概述

底层数据结构是数组,查询快,增删慢,线程安全,效率低。

4.1.3 Vector类特有功能

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

4.1.4 LinkedList类概述

底层数据结构是链表,查询慢,增删快,线程不安全,效率高

方法声明 功能描述
public void addFirst(E e) 将指定元素插入此列表的开头
public voidaddLast(E e) 将指定元素添加到此列表的结尾
public E getFirst() 将指定元素添加到此列表的结尾
public E getLast() 获取集合的最后一个元素
public E removeFirst() 删除集合的第一个元素
public E removeLast() 删除最后一个元素

代码示例:使用LinkedList来模拟一个栈数据结构

package cn.itcast;

import java.util.LinkedList;

/*
 *使用LinkedList模拟栈数据结构的集合,并测试
 *1、栈的特点先进后出
 *2、 LinkedList的特有添加功能addFirst()
 */
class MyStack {
    private LinkedList link;

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

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

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

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

/*
 * MyStack的测试
 */
public class MyStackDemo {
    public static void main(String[] args) {
        // 创建集合对象
        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());
        }
    }
}

运行结果:


4.2 Set接口概述

一个不包含重复元素的 collection,无序。

哈希表确定元素是否相同

1、 判断的是两个元素的哈希值是否相同。
如果相同,再判断两个对象的内容是否相同。

2、 判断哈希值相同,其实判断的是对象的HashCode方法。判断内容相同,用的是equals方法。

4.2.1 HashSet类概述

  • 不保证 set 的迭代顺序,特别是它不保证该顺序恒久不变。
  • HashSet如何保证元素唯一性
  • 底层数据结构是哈希表(元素是链表的数组)
  • 哈希表依赖于哈希值存储
  • 添加功能底层依赖两个方法:int hashCode()、boolean equals(Object obj)

HashSet存储元素保证唯一性的代码及图解:

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集合存储自定义对象并遍历。如果对象的成员变量值相同即为同一个对象
 * 
 * 注意了: 你使用的是HashSet集合,这个集合的底层是哈希表结构。 而哈希表结构底层依赖:hashCode()和equals()方法。
 * 如果你认为对象的成员变量值相同即为同一个对象的话,你就应该重写这两个方法。 如何重写呢?不同担心,自动生成即可。
 */
public class DogDemo {
    public static void main(String[] args) {
        // 创建集合对象
        HashSet<Dog> hs = new HashSet<Dog>();

        // 创建狗对象
        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());
        }
    }
}

运行结果:


4.2.2 LinkedHashSet类概述

元素有序唯一,由链表保证元素有序,由哈希表保证元素唯一。

4.3 TreeSet类概述

使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。

  • TreeSet是如何保证元素的排序和唯一性
    底层数据结构是红黑树(红黑树是一种自平衡的二叉树)

  • TreeSet判断元素唯一性的方式
    就是根据比较方法的返回结果是否是0,是0,就是相同元素,不存。

  • TreeSet对元素进行排序的方式一
    让元素自身具备比较功能,元素就需要实现Comparable接口,覆盖compareTo方法。
    如果不要按照对象中具备的自然顺序进行排序。如果对象中不具备自然顺序。怎么办?

  • 可以使用TreeSet集合第二种排序方式
    让集合自身具备比较功能,定义一个类实现Comparator接口,覆盖compare方法。将该类对象作为参数传递给TreeSet集合的构造函数。

TreeSet存储元素自然排序和唯一的图解:

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
        // 姓名长度
        int num = s1.getName().length() - s2.getName().length();
        // 姓名内容
        int num2 = num == 0 ? s1.getName().compareTo(s2.getName()) : num;
        // 年龄
        int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
        return num3;
    }

}

/*
 * 需求:请按照姓名的长度排序
 * 
 * TreeSet集合保证元素排序和唯一性的原理 唯一性:是根据比较的返回是否是0来决定。 排序: A:自然排序(元素具备比较性)
 * 让元素所属的类实现自然排序接口 Comparable B:比较器排序(集合具备比较性) 让集合的构造方法接收一个比较器接口的子类对象 Comparator
 */
public class TreeSetDemo {
    public static void main(String[] args) {
        // 创建集合对象
        // TreeSet<Student> ts = new TreeSet<Student>(); //自然排序
        // public TreeSet(Comparator comparator) //比较器排序
        // TreeSet<Student> ts = new TreeSet<Student>(new MyComparator());

        // 如果一个方法的参数是接口,那么真正要的是接口的实现类的对象
        // 而匿名内部类就可以实现这个东西
        TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() {
            public int compare(Student s1, Student s2) {
                // 姓名长度
                int num = s1.getName().length() - s2.getName().length();
                // 姓名内容
                int num2 = num == 0 ? s1.getName().compareTo(s2.getName())
                        : num;
                // 年龄
                int num3 = num2 == 0 ? s1.getAge() - s2.getAge() : num2;
                return num3;
            }
        });

        // 创建元素
        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());
        }
    }
}

运行结果:


4.4 集合的遍历

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

而每一个容器的数据结构不同,所以取出的动作细节也不一样。但是都具有共性内容: 判断和取出。那么就可以将这些共性抽取。那么这些内部类都符合一个规则(或者说都抽取出来一个规则)。该规则就是Iterator。通过一个对外提供的方法:iterator();,来获取集合的取出对象。因为Collection中有iterator方法,所以每一个子类集合对象都具备迭代器。

迭代的常见操作


PS:在迭代时循环中next调用一次,就要hasNext判断一次。

并发修改异常,原因:迭代器依赖于集合存在,修改集合元素而迭代器却不知道。

解决方法:

A:迭代器迭代元素,迭代器修改。因为Iterator没有添加功能,所以使用其子接口ListIterator,元素在迭代元素的后面添加。
B:集合遍历元素,集合修改元素(普通for和get(index)结合),元素在最后添加

package cn.itcast;

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

/*
 * 问题:有一个集合,如下,请问,我想判断里面有没有"world"这个元素,如果有,我就添加一个"javaee"元素,请写代码实现。
 * 
 * ConcurrentModificationException:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常。 
 * 产生的原因:
 * 迭代器是依赖于集合而存在的,在判断成功后,集合的中新添加了元素,而迭代器却不知道,所以就报错了,这个错叫并发修改异常。
 * 其实这个问题描述的是:迭代器遍历元素的时候,通过集合是不能修改元素的。
 * 如何解决呢?
 * A:迭代器迭代元素,迭代器修改元素,元素是跟在刚才迭代的元素后面的。
 * B:集合遍历元素,集合修改元素(普通for),元素在最后添加的。
 */
public class ListIteratorDemo {
    public static void main(String[] args) {
        // 创建List集合对象
        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接口概述

将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值。其实Map集合中存储的就是键值对。map集合中必须保证键的唯一性。

Map接口和Collection接口的不同

  • Map是双列的,Collection是单列的
  • Map的键唯一,Collection的子体系Set是唯一的
  • Map集合的数据结构值针对键有效,跟值无关
  • Collection集合的数据结构是针对元素有效

Map常用的子类:

  • Hashtable:内部结构是哈希表,是同步的。不允许null作为键,null作为值。
  • Properties:用来存储键值对型的配置文件的信息,可以和IO技术相结合。
  • HashMap:内部结构式哈希表,不是同步的。允许null作为键,null作为值。
  • TreeMap:内部结构式二叉树,不是同步的。可以对Map结合中的键进行排序。
  • HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。

5.2 Map集合遍历

方式1:根据键找值。获取所有键的集合,遍历键的集合,获取到每一个键,根据键找值。

package cn.itcast;

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

/*
 * Map集合的遍历。
 * Map -- 夫妻对
 * 思路:
 *      A:把所有的丈夫给集中起来。
 *      B:遍历丈夫的集合,获取得到每一个丈夫。
 *      C:让丈夫去找自己的妻子。
 * 
 * 转换:
 *      A:获取所有的键
 *      B:遍历键的集合,获取得到每一个键
 *      C:根据键去找值
 */
public class MapDemo {
    public static void main(String[] args) {
        // 创建集合对象
        Map<String, String> map = new HashMap<String, String>();

        // 创建元素并添加到集合
        map.put("杨过", "小龙女");
        map.put("郭靖", "黄蓉");
        map.put("杨康", "穆念慈");
        map.put("陈玄风", "梅超风");

        // 遍历
        // 获取所有的键
        Set<String> set = map.keySet();
        // 遍历键的集合,获取得到每一个键
        for (String key : set) {
            // 根据键去找值
            String value = map.get(key);
            System.out.println(key + "---" + value);
        }
    }
}

方式2:根据键值对对象找键和值。

  • 获取所有键值对对象的集合
  • 遍历键值对对象的集合,获取到每一个键值对对象
  • 根据键值对对象找键和值
package cn.itcast;

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

/*
 * Map集合的遍历。
 * Map -- 夫妻对
 * 
 * 思路:
 *      A:获取所有结婚证的集合
 *      B:遍历结婚证的集合,得到每一个结婚证
 *      C:根据结婚证获取丈夫和妻子
 * 
 * 转换:
 *      A:获取所有键值对对象的集合
 *      B:遍历键值对对象的集合,得到每一个键值对对象
 *      C:根据键值对对象获取键和值
 * 
 * 这里面最麻烦的就是键值对对象如何表示呢?
 * 看看我们开始的一个方法:
 *      Set<Map.Entry<K,V>> entrySet():返回的是键值对对象的集合
 */
public class MapDemo {
    public static void main(String[] args) {
        // 创建集合对象
        Map<String, String> map = new HashMap<String, String>();

        // 创建元素并添加到集合
        map.put("杨过", "小龙女");
        map.put("郭靖", "黄蓉");
        map.put("杨康", "穆念慈");
        map.put("陈玄风", "梅超风");

        // 获取所有键值对对象的集合
        Set<Map.Entry<String, String>> set = map.entrySet();
        // 遍历键值对对象的集合,得到每一个键值对对象
        for (Map.Entry<String, String> me : set) {
            // 根据键值对对象获取键和值
            String key = me.getKey();
            String value = me.getValue();
            System.out.println(key + "---" + value);
        }
    }
}

3、HashMap类概述

键是哈希表结构,可以保证键的唯一性

4、LinkedHashMap类概述

Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。

5、TreeMap类概述

键是红黑树结构,可以保证键的排序和唯一性,自然排序,比较器排序。

6、Map集合的应用及扩展

package cn.itcast;

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

/*
 * 需求 :"aababcabcdabcde",获取字符串中每一个字母出现的次数要求结果:a(5)b(4)c(3)d(2)e(1)
 * 
 * 分析:
 *      A:定义一个字符串(可以改进为键盘录入)
 *      B:定义一个TreeMap集合
 *          键:Character
 *          值:Integer
 *      C:把字符串转换为字符数组
 *      D:遍历字符数组,得到每一个字符
 *      E:拿刚才得到的字符作为键到集合中去找值,看返回值
 *          是null:说明该键不存在,就把该字符作为键,1作为值存储
 *          不是null:说明该键存在,就把值加1,然后重写存储该键和值
 *      F:定义字符串缓冲区变量
 *      G:遍历集合,得到键和值,进行按照要求拼接
 *      H:把字符串缓冲区转换为字符串输出
 * 
 * 录入:linqingxia
 * 结果:result:a(1)g(1)i(3)l(1)n(2)q(1)x(1)
 */
public class TreeMapDemo {
    public static void main(String[] args) {
        // 定义一个字符串(可以改进为键盘录入)
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String line = sc.nextLine();

        // 定义一个TreeMap集合
        TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>();

        // 把字符串转换为字符数组
        char[] chs = line.toCharArray();

        // 遍历字符数组,得到每一个字符
        for (char ch : chs) {
            // 拿刚才得到的字符作为键到集合中去找值,看返回值
            Integer i = tm.get(ch);

            // 是null:说明该键不存在,就把该字符作为键,1作为值存储
            if (i == null) {
                tm.put(ch, 1);
            } else {
                // 不是null:说明该键存在,就把值加1,然后重写存储该键和值
                i++;
                tm.put(ch, i);
            }
        }

        // 定义字符串缓冲区变量
        StringBuilder sb = new StringBuilder();

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

        // 把字符串缓冲区转换为字符串输出
        String result = sb.toString();
        System.out.println("result:" + result);
    }
}

示例2:在很多项目中,应用比较多的是一对多的映射关系,这就可以通过嵌套的形式将多个映射定义到一个大的集合中,并将大的集合分级处理,形成一个体系。

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  北京校区
 *          jc  基础班
 *                  林青霞     27
 *                  风清扬     30
 *          jy  就业班 
 *                  赵雅芝     28
 *                  武鑫      29
 *      sh  上海校区
 *          jc  基础班
 *                  郭美美     20
 *                  犀利哥     22
 *          jy  就业班 
 *                  罗玉凤     21
 *                  马征      23
 *      gz  广州校区
 *          jc  基础班
 *                  王力宏     30
 *                  李静磊     32
 *          jy  就业班 
 *                  郎朗      31
 *                  柳岩      33
 *      xa  西安校区
 *          jc  基础班
 *                  范冰冰     27
 *                  刘意      30
 *          jy  就业班 
 *                  李冰冰     28
 *                  张志豪     29
 */
public class HashMapDemo {
    public static void main(String[] args) {
        // 创建大集合
        HashMap<String, HashMap<String, ArrayList<Student>>> czbkMap = new HashMap<String, HashMap<String, ArrayList<Student>>>();

        // 北京校区数据
        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("风清扬", 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("基础班", array1);
        bjCzbkMap.put("就业班", array2);
        czbkMap.put("北京校区", bjCzbkMap);

        // 西安校区数据
        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("基础班", array3);
        xaCzbkMap.put("就业班", array4);
        czbkMap.put("西安校区", 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());
                }
            }
        }
    }
}

运行结果:

6. 集合框架的综合应用

代码示例:模拟斗地主洗牌和发牌

package cn.itcast_04;

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

/*
 * 思路:
 *      A:创建一个HashMap集合
 *      B:创建一个ArrayList集合
 *      C:创建花色数组和点数数组
 *      D:从0开始往HashMap里面存储编号,并存储对应的牌
 *        同时往ArrayList里面存储编号即可。
 *      E:洗牌(洗的是编号)
 *      F:发牌(发的也是编号,为了保证编号是排序的,就创建TreeSet集合接收)
 *      G:看牌(遍历TreeSet集合,获取编号,到HashMap集合找对应的牌)
 */
public class PokerDemo {
    public static void main(String[] args) {
        // 创建一个HashMap集合
        HashMap<Integer, String> hm = new HashMap<Integer, String>();

        // 创建一个ArrayList集合
        ArrayList<Integer> array = new ArrayList<Integer>();

        // 创建花色数组和点数数组
        // 定义一个花色数组
        String[] colors = { "♠", "♥", "♣", "♦" };
        // 定义一个点数数组
        String[] numbers = { "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q",
                "K", "A", "2", };

        // 从0开始往HashMap里面存储编号,并存储对应的牌,同时往ArrayList里面存储编号即可。
        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);

        // 洗牌(洗的是编号)
        Collections.shuffle(array);

        // 发牌(发的也是编号,为了保证编号是排序的,就创建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集合,获取编号,到HashMap集合找对应的牌)
        lookPoker("风清扬", 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();
    }
}

运行结果:

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,194评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,058评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,780评论 0 346
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,388评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,430评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,764评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,907评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,679评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,122评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,459评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,605评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,270评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,867评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,734评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,961评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,297评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,472评论 2 348

推荐阅读更多精彩内容

  • 坚持有空就写点东西,算是回顾复习。 Java集合框架下大致可以分为如下五个部分:List列表、Set集合、Map映...
    锋Plus阅读 289评论 0 1
  • 一、集合框架的概述 1、概述: 1、简述:所谓集合,就是为方便对多个对象的操作,对对象进行存储。集合就是存储对象最...
    玉圣阅读 508评论 0 4
  • 概述 Java集合框架由Java类库的一系列接口、抽象类以及具体实现类组成。我们这里所说的集合就是把一组对象组织到...
    absfree阅读 1,251评论 0 10
  • Collection ├List │├LinkedList │├ArrayList │└Vector │└Stac...
    AndyZX阅读 870评论 0 1
  • 1. Collections工具类 1.1 Collections类概述 针对集合操作 的工具类,里面的方法都是静...
    JackChen1024阅读 236评论 0 0