Java基础-Collection之Set的实现
2015-08-08 00:58
726 查看
Collection体系:
|–List——特点:元素有序(指的是元素的存入和取出的顺序一致),元素可重复
–||–ArrayList——特点:底层是数组结构,查询快,增删慢;线程不同步,效率高
–||–Vector——特点:底层是数组结构,查询快,增删慢;线程同步,效率低(基本上已经被ArrayList替代)
–||–LinkedList——特点:底层是链表结构,增删快,查询慢;线程不同步,效率高
|–Set——特点:元素无序(指的是元素的存入和取出的顺序有可能不一致),元素唯一
–||–HashSet——特点:底层是哈希结构,线程不同步,无序,高效
–||–TreeSet——特点:底层是二叉树结构,线程不同步,可以对Set集合中的元素进行指定顺序的排序。(自然顺序或自定义排序)
前面已经学过了Collection体系中的List的实现子类了,今天将学习到的Set的实现子类以及一些重要的知识点总结一下
学习集合体系的标准:学习顶层,使用底层
在Set体系中,有两个实现子类:HashSet和TreeSet
首先,来学习一下Set这个顶层所具备的功能
通过查询API,我发现,Set体系中定义的功能完全和Collection中定义的功能一致,因此,就不在这里赘述了,直接使用:
学习Set集合无非是学习:
1、创建一个集合
2、创建元素对象
3、往集合里添加元素
4、遍历
A:迭代器
B:增强for
创建一个Set集合的方法,由于Set是一个接口,不能通过new来新建对象,我们可以通过下面三种方式来创建一个Set集合
由于,set体系中的方法和Collection中定义的方法一样,那么我们现在直接来走一遍学习集合的流程
创建集合、创建元素、添加元素、遍历
代码如下:
结果:
从结果可以看出,1、我们存储元素的顺序和取出来的顺序是不同的,这就印证了Set体系中的集合的元素是无序的
2、在程序中,我们添加了两个“world”字符串,但是在遍历的时候却没有两个“world”,这印证了Set集合中的元
素是唯一的。后面学习的HashSet和TreeSet会详细分析保证元素唯一是如何实现的。
HashSet是Set体系中的一个子实现类
特点:特点:底层是哈希结构,线程不同步,无序,高效
HashSet集合保证元素唯一性:通过元素的hashCode方法,和equals方法完成的。
当元素的hashCode值相同时,才继续判断元素的equals是否为true。
如果为true,那么视为相同元素,不存。如果为false,那么存储。
如果hashCode值不同,那么不判断equals,从而提高对象比较的速度。
HashSet存储字符串并遍历
结果:
分析:
在HashSet中添加了两个“java”元素,但是输出来只有1个,是因为String类实现了hashCode()和equals()方法。
那么,现在问题来了,当我们要存储自定义的对象时,该如何保证HashSet中元素的唯一性呢?
我们都知道,当我们new出来多个对象时,往HashSet中添加时,每个对象的地址值都是不同的,那么就算我们有两个属性一模一样
的对象,HashSet仍然认为是两个不同的对象,但是现实生活中,我们就认为这是同一个对象,其中一个不应该添加进HashSet集合中。
图解HashSet保证元素唯一性:
上面我们说过,在HashSet里面,是通过元素(也就是我们现在的对象)hashCode()和equals()方法来保证元素的唯一性。那么我们该如何来实现这两个方法呢?
通过观看原码,我们发现这是一个相当复杂的过程,但是IDE给我们提供了最大的方便,可以一键生成hashCode()和equals()方法。在开发中,我们只需要自动生成就好了。
那么现在,我们现在来看一下,在没有实现这两个方法的时候,HashSet是不能保证元素唯一的情况
结果:
分析:
这里标红的两个元素,在我们看来就属于同一个对象,但是HashSet并没能识别出来,是因为在Student类里面,没有实现hashCode()和equls()方法。
下面我们改进一下代码,让HashSet在存储我们自定义对象的时候,能识别出来
结果:
分析:
由于在Student类中,我们实现了hashCode()和equals()方法,那么在属性一样的Student对象情况下,只能添加一个。
学习完HashSet后,我们来学习一下TreeSet
TreeSet 最大的特点是可以对集合中的元素进行自然顺序的(字典顺序)或者自定义方式 排序。同时还保证元素的唯一性
图解TreeSet保证元素唯一性:
下面来重点讲解TreeSet实现对元素排序的两种方式:(这里主要是针对自定义对象的排序)
方式一:自定义所在的类实现Comparable接口,并且重写CompareTo方法。
此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。
方式二:比较器的使用。Comparator接口。这里有两种使用方法:1、自定义一个比较器,实现Comparator接口,重写其中的compare()
方法;2、直接使用TreeSet的带参构造方法,并且在参数位置使用Comparator的一个自实现类,即匿名内部类。
先来学习下,TreeSet对String类型数据保持唯一性和排序的例子:
代码:
结果:
分析:
1、元素输出的顺序和我们传入的顺序不一致,而且是按照一定的顺序来输出,是因为在存入的时候,就按照了自然顺序存入;
2、代码中,添加了两个“world”元素,但是只有一个被输出来,是因为第二个没有被添加进去。是如何实现的呢?
是因为在String类中,实现了Camparable接口,并且重写了compareTo方法。
这一点可以从原码中看出来
现在,我们要实现TreeSet存储自定义对象时,也保证元素唯一和排序
国际惯例:先看一下错误的示范:(对象所在的类,既没有实现Comparable接口,在创建TreeSet是,也没有使用带参构造方法,并且传入
Comparatoe的匿名内部类)
Student.java代码
结果:
分析:
1、ClassCastException:类类型转换异常。这个异常,我们在继承的时候遇到过,发生的原因主要是,两个没有继承或者实现关系
的类进行类型转换。这里也一样,因为Student没有实现Comparable接口。
下面让Student实现Comparable接口,并且重写compareTo方法
结果:
分析:
1、结果中,数据实现了排序,也保证了元素的唯一性。主要规则,在compareTo()方法中。
我们可以在该方法中,定义属于具体需要的具体规则。如按年龄大小,按名字长短等等。
下面,我用匿名内部类的方式,实现同样的功能。这次,Student类就不需要实现Comparable接口了
开发中,推荐使用该方法,因为,开发中有一个原则,对修改关闭,对实现开放。怎么理解呢?就是说在我们的具体类中,定义好就尽量不要
改动,因为可能这个类与其他若干个类有各种关系,修改了一个地方,可能影响到其他类的功能。
Student.java代码
结果:
分析:
1、这样做可以实现同样的功能。
2、需要理解匿名内部类的使用。
Collection和Collections
Collections的功能:
排序:public static void sort(List list)
二分查找:public static int binarySearch(List list,T key)
反转:public static void reverse(List list)
最大值:public static T max(Collection coll)
随机置换:public static void shuffle(List list)
马上使用之:
代码:
有了Collections的随机置换功能,我们可以模拟一下斗地主发牌的功能
代码
结果:
不分析了,大家看看哪一家会赢!!!
|–List——特点:元素有序(指的是元素的存入和取出的顺序一致),元素可重复
–||–ArrayList——特点:底层是数组结构,查询快,增删慢;线程不同步,效率高
–||–Vector——特点:底层是数组结构,查询快,增删慢;线程同步,效率低(基本上已经被ArrayList替代)
–||–LinkedList——特点:底层是链表结构,增删快,查询慢;线程不同步,效率高
|–Set——特点:元素无序(指的是元素的存入和取出的顺序有可能不一致),元素唯一
–||–HashSet——特点:底层是哈希结构,线程不同步,无序,高效
–||–TreeSet——特点:底层是二叉树结构,线程不同步,可以对Set集合中的元素进行指定顺序的排序。(自然顺序或自定义排序)
前面已经学过了Collection体系中的List的实现子类了,今天将学习到的Set的实现子类以及一些重要的知识点总结一下
学习集合体系的标准:学习顶层,使用底层
在Set体系中,有两个实现子类:HashSet和TreeSet
首先,来学习一下Set这个顶层所具备的功能
通过查询API,我发现,Set体系中定义的功能完全和Collection中定义的功能一致,因此,就不在这里赘述了,直接使用:
学习Set集合无非是学习:
1、创建一个集合
2、创建元素对象
3、往集合里添加元素
4、遍历
A:迭代器
B:增强for
创建一个Set集合的方法,由于Set是一个接口,不能通过new来新建对象,我们可以通过下面三种方式来创建一个Set集合
[code]// 创建集合对象 Collection<String> c = new HashSet<String>(); Set<String> set = new HashSet<String>(); HashSet<String> hs = new HashSet<String>();
[code]以上三种方法,都可以创建一个Set的集合
由于,set体系中的方法和Collection中定义的方法一样,那么我们现在直接来走一遍学习集合的流程
创建集合、创建元素、添加元素、遍历
代码如下:
[code]public class SetDemo { public static void main(String[] args) { // 创建集合对象 Set<String> set = new HashSet<String>(); // 创建并添加元素 set.add("hello"); set.add("world"); set.add("java"); set.add("world"); // 迭代器遍历 Iterator<String> it = set.iterator(); while (it.hasNext()) { String s = it.next(); System.out.println(s); } System.out.println("--------------"); //增强for遍历 for (String s : set) { System.out.println(s); } } }
结果:
从结果可以看出,1、我们存储元素的顺序和取出来的顺序是不同的,这就印证了Set体系中的集合的元素是无序的
2、在程序中,我们添加了两个“world”字符串,但是在遍历的时候却没有两个“world”,这印证了Set集合中的元
素是唯一的。后面学习的HashSet和TreeSet会详细分析保证元素唯一是如何实现的。
HashSet是Set体系中的一个子实现类
特点:特点:底层是哈希结构,线程不同步,无序,高效
HashSet集合保证元素唯一性:通过元素的hashCode方法,和equals方法完成的。
当元素的hashCode值相同时,才继续判断元素的equals是否为true。
如果为true,那么视为相同元素,不存。如果为false,那么存储。
如果hashCode值不同,那么不判断equals,从而提高对象比较的速度。
HashSet存储字符串并遍历
[code]public class HashSetDemo { public static void main(String[] args) { // 创建集合对象 HashSet<String> hs = new HashSet<String>(); // 创建并添加元素 hs.add("hello"); hs.add("world"); hs.add("java"); hs.add("java"); // 遍历 for (String s : hs) { System.out.println(s); } } }
结果:
分析:
在HashSet中添加了两个“java”元素,但是输出来只有1个,是因为String类实现了hashCode()和equals()方法。
那么,现在问题来了,当我们要存储自定义的对象时,该如何保证HashSet中元素的唯一性呢?
我们都知道,当我们new出来多个对象时,往HashSet中添加时,每个对象的地址值都是不同的,那么就算我们有两个属性一模一样
的对象,HashSet仍然认为是两个不同的对象,但是现实生活中,我们就认为这是同一个对象,其中一个不应该添加进HashSet集合中。
图解HashSet保证元素唯一性:
上面我们说过,在HashSet里面,是通过元素(也就是我们现在的对象)hashCode()和equals()方法来保证元素的唯一性。那么我们该如何来实现这两个方法呢?
通过观看原码,我们发现这是一个相当复杂的过程,但是IDE给我们提供了最大的方便,可以一键生成hashCode()和equals()方法。在开发中,我们只需要自动生成就好了。
那么现在,我们现在来看一下,在没有实现这两个方法的时候,HashSet是不能保证元素唯一的情况
[code]Student.java
[code]public class Student { private String name; private int age; public Student() { } public Student(String name, int age) { 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; } }
[code]HashSetDemo.java
[code]public class HashSetDemo2 { public static void main(String[] args) { // 创建集合对象 HashSet<Student> hs = new HashSet<Student>(); // 创建元素对象 Student s1 = new Student("林青霞", 26); Student s2 = new Student("张曼玉", 36); Student s3 = new Student("周慧敏", 20); Student s4 = new Student("林青霞", 26); Student s5 = new Student("林青霞", 66); Student s6 = new Student("林志玲", 16); // 添加元素 hs.add(s1); // hs.add(s1); hs.add(s2); hs.add(s3); hs.add(s4); hs.add(s5); hs.add(s6); // 遍历 for (Student s : hs) { System.out.println(s.getName() + "***" + s.getAge()); } } }
结果:
分析:
这里标红的两个元素,在我们看来就属于同一个对象,但是HashSet并没能识别出来,是因为在Student类里面,没有实现hashCode()和equls()方法。
下面我们改进一下代码,让HashSet在存储我们自定义对象的时候,能识别出来
[code]改进版Student.java代码
[code]public class Student { private String name; private int age; public Student() { } public Student(String name, int age) { 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 int hashCode() { // // return 0; // /* // * name:30,age:40 // * name:20,age:50 // */ // return this.name.hashCode() + this.age*13; // } // // @Override // public boolean equals(Object obj) { // // System.out.println(this + "------------------------------" + obj); // if (this == obj) { // return true; // } // // if (!(obj instanceof Student)) { // return false; // } // // Student s = (Student) obj; // return this.name.equals(s.name) && this.age == s.age; // } @Override public String toString() { return "Student [name=" + name + ", age=" + age + "]"; } @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; } }
结果:
分析:
由于在Student类中,我们实现了hashCode()和equals()方法,那么在属性一样的Student对象情况下,只能添加一个。
学习完HashSet后,我们来学习一下TreeSet
TreeSet 最大的特点是可以对集合中的元素进行自然顺序的(字典顺序)或者自定义方式 排序。同时还保证元素的唯一性
图解TreeSet保证元素唯一性:
下面来重点讲解TreeSet实现对元素排序的两种方式:(这里主要是针对自定义对象的排序)
方式一:自定义所在的类实现Comparable接口,并且重写CompareTo方法。
此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法。
方式二:比较器的使用。Comparator接口。这里有两种使用方法:1、自定义一个比较器,实现Comparator接口,重写其中的compare()
方法;2、直接使用TreeSet的带参构造方法,并且在参数位置使用Comparator的一个自实现类,即匿名内部类。
先来学习下,TreeSet对String类型数据保持唯一性和排序的例子:
代码:
[code]import java.util.TreeSet; /* * TreeSet可以对元素进行排序。 * 使用元素的自然顺序对元素进行排序,或者根据创建 set 时提供的 Comparator 进行排序,具体取决于使用的构造方法。 */ public class TreeSetDemo { public static void main(String[] args) { // 创建集合对象 TreeSet<String> ts = new TreeSet<String>(); // 创建并添加元素 ts.add("hello"); ts.add("world"); ts.add("java"); ts.add("abcde"); ts.add("zone"); ts.add("world"); // 遍历 for (String str : ts) { System.out.println(str); } } }
结果:
分析:
1、元素输出的顺序和我们传入的顺序不一致,而且是按照一定的顺序来输出,是因为在存入的时候,就按照了自然顺序存入;
2、代码中,添加了两个“world”元素,但是只有一个被输出来,是因为第二个没有被添加进去。是如何实现的呢?
是因为在String类中,实现了Camparable接口,并且重写了compareTo方法。
这一点可以从原码中看出来
现在,我们要实现TreeSet存储自定义对象时,也保证元素唯一和排序
国际惯例:先看一下错误的示范:(对象所在的类,既没有实现Comparable接口,在创建TreeSet是,也没有使用带参构造方法,并且传入
Comparatoe的匿名内部类)
Student.java代码
[code]public class Student { private String name; private int age; public Student() { } public Student(String name, int age) { 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 int compareTo(Student s) { // // 需求是比较年龄 // int num = this.age - s.age; // // 由于对象有多个成员变量,你不能根据其中的某一个决定其他的。 // // 当某一个相同的时候,你还需要判断其他的是不是也是相同的。 // int num2 = (num == 0) ? (this.name.compareTo(s.name)) : num; // return num2; // } // 需求:我想按照姓名的长度排序,从小到大排序。怎么做? // @Override // public int compareTo(Student s) { // // 姓名的长度 // int num = this.name.length() - s.name.length(); //// System.out.println(num); // // 很多时候,别人给我们的需求其实只是一个主要需要 // // 还有很多的次要需求是需要我们自己进行分析的。 // // 比较姓名的内容 // int num2 = (num == 0) ? (this.name.compareTo(s.name)) : num; // // 继续分析,姓名长度和内容都相同的情况下,年龄还可能不一样呢? // // 所以,当姓名长度和内容都相同的时候,我们在比较下年龄就好了 // int num3 = (num2 == 0) ? (this.age - s.age) : num2; // return num3; // } }
[code]TreeSetDemo2.java代码
[code]public class TreeSetDemo2 { public static void main(String[] args) { // 创建集合对象 TreeSet<Student> ts = new TreeSet<Student>(); // 创建元素对象 Student s1 = new Student("liudehua", 52); Student s2 = new Student("chenglong", 60); Student s3 = new Student("zhouxinchi", 44); Student s4 = new Student("sunyanzi", 34); Student s5 = new Student("linqingxia", 26); Student s6 = new Student("linqingxia", 36); Student s7 = new Student("linqing", 26); Student s8 = new Student("linqingxia", 26); // 添加元素 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()); } } }
结果:
分析:
1、ClassCastException:类类型转换异常。这个异常,我们在继承的时候遇到过,发生的原因主要是,两个没有继承或者实现关系
的类进行类型转换。这里也一样,因为Student没有实现Comparable接口。
下面让Student实现Comparable接口,并且重写compareTo方法
[code]Student.java代码
[code] public class Student implements Comparable<Student> { private String name; private int age; public Student() { } public Student(String name, int age) { 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 int compareTo(Student s) { // // 需求是比较年龄 // int num = this.age - s.age; // // 由于对象有多个成员变量,你不能根据其中的某一个决定其他的。 // // 当某一个相同的时候,你还需要判断其他的是不是也是相同的。 // int num2 = (num == 0) ? (this.name.compareTo(s.name)) : num; // return num2; // } // 需求:我想按照姓名的长度排序,从小到大排序。怎么做? @Override public int compareTo(Student s) { // 姓名的长度 int num = this.name.length() - s.name.length(); // System.out.println(num); // 很多时候,别人给我们的需求其实只是一个主要需要 // 还有很多的次要需求是需要我们自己进行分析的。 // 比较姓名的内容 int num2 = (num == 0) ? (this.name.compareTo(s.name)) : num; // 继续分析,姓名长度和内容都相同的情况下,年龄还可能不一样呢? // 所以,当姓名长度和内容都相同的时候,我们在比较下年龄就好了 int num3 = (num2 == 0) ? (this.age - s.age) : num2; return num3; } }
[code]TreeSetDemo2.java代码不变
结果:
分析:
1、结果中,数据实现了排序,也保证了元素的唯一性。主要规则,在compareTo()方法中。
我们可以在该方法中,定义属于具体需要的具体规则。如按年龄大小,按名字长短等等。
下面,我用匿名内部类的方式,实现同样的功能。这次,Student类就不需要实现Comparable接口了
开发中,推荐使用该方法,因为,开发中有一个原则,对修改关闭,对实现开放。怎么理解呢?就是说在我们的具体类中,定义好就尽量不要
改动,因为可能这个类与其他若干个类有各种关系,修改了一个地方,可能影响到其他类的功能。
Student.java代码
[code]public class Student { private String name; private int age; public Student() { } public Student(String name, int age) { 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; } }
[code]TreeSetDemo2.java代码
[code]/* * 比较器接口 Comparator。带参构造。 * * 开发原则: * 对修改关闭,对扩展开放。 */ public class TreeSetDemo { public static void main(String[] args) { // 创建集合对象 // public TreeSet(Comparator comparator) // Comparator c = new MyComparator(); // TreeSet<Student> ts = new TreeSet<Student>(c); // 两句写一句 // TreeSet<Student> ts = new TreeSet<Student>(new MyComparator()); // 匿名内部类 TreeSet<Student> ts = new TreeSet<Student>(new Comparator<Student>() { @Override public int compare(Student s1, Student s2) { // 按年龄排序,从小到大 int num = s1.getAge() - s2.getAge(); // 次要条件 int num2 = (num == 0) ? (s1.getName().compareTo(s2.getName())) : num; return num2; } }); // 创建元素对象 Student s1 = new Student("liudehua", 52); Student s2 = new Student("chenglong", 60); Student s3 = new Student("zhouxinchi", 44); Student s4 = new Student("sunyanzi", 34); Student s5 = new Student("linqingxia", 26); Student s6 = new Student("linqingxia", 36); Student s7 = new Student("linqing", 26); Student s8 = new Student("linqingxia", 26); // 添加元素 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()); } } }
结果:
分析:
1、这样做可以实现同样的功能。
2、需要理解匿名内部类的使用。
Collection和Collections
[code]区别:(面试题) Collection:是Collection集合的顶层接口,定义了Collection集合的共性方法。 Collections:是一个类,定义了针对Collection集合操作的功能。有排序,查找,反转等。
Collections的功能:
排序:public static void sort(List list)
二分查找:public static int binarySearch(List list,T key)
反转:public static void reverse(List list)
最大值:public static T max(Collection coll)
随机置换:public static void shuffle(List list)
马上使用之:
代码:
[code]public class CollectionsDemo { public static void main(String[] args) { // 创建集合对象 ArrayList<Integer> array = new ArrayList<Integer>(); // 添加元素 array.add(60); array.add(25); array.add(38); array.add(213); array.add(99); array.add(22); System.out.println("array:" + array); // 排序 // public static void sort(List list) // Collections.sort(array); // System.out.println("array:" + array); // 二分查找 // public static <T> int binarySearch(List list,T key) // [22, 25, 38, 60, 99, 213] // int index = Collections.binarySearch(array, 60); // System.out.println("index:" + index); // 反转 // public static void reverse(List list) // [60, 25, 38, 213, 99, 22] // Collections.reverse(array); // System.out.println("array:" + array); // 最大值 // public static T max(Collection coll) // Integer i = Collections.max(array); // System.out.println(i); // 随机置换:public static void shuffle(List list) Collections.shuffle(array); System.out.println("array:" + array); } }
有了Collections的随机置换功能,我们可以模拟一下斗地主发牌的功能
代码
[code]/* * 斗地主: * 模拟斗地主发牌 * * 思路: * 买牌 * 黑桃A、2、 3、 4、 5、 6、 7、 8、 9、 J、 Q、 K * 红桃A、2、 3、 4、 5、 6、 7、 8、 9、 J、 Q、 K * 梅花A、2、 3、 4、 5、 6、 7、 8、 9、 J、 Q、 K * 方块A、2、 3、 4、 5、 6、 7、 8、 9、 J、 Q、 K * 大王、小王 * 洗牌 * 利用Collections 的随机置换方法 * 发牌 * 发给3个人 * 看牌 * 留三张 */ import java.lang.reflect.Array; import java.util.ArrayList; import java.util.Collections; public class DouDiZhu { public static void main(String[] args) { // 创建一个数组,表示花色 String[] colors = { "黑桃", "红桃", "梅花", "方块" }; // 创建一个表示数字的数组 String[] number = { "A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K" }; // 造一个牌盒 ArrayList<String> array = new ArrayList<String>(); // 想把大小王装进去 array.add("大王"); array.add("小王"); // 增强for循环装牌 for (String c : colors) { for (String n : number) { // 组合牌 String s = c + n; // 装牌 array.add(s); } } // 打印一下牌 // System.out.print(array); // 洗牌 Collections.shuffle(array); // 打印一下洗牌后的牌 // System.out.print(array); // 发牌,3个人,定义3个集合 ArrayList<String> weiweiList = new ArrayList<String>(); ArrayList<String> minminList = new ArrayList<String>(); ArrayList<String> guangtouList = new ArrayList<String>(); // 循环发牌,由于需要留三张牌,所以只能循环到array.size()-3 for (int x = 0; x < array.size()-3; x++) { // 轮着发三张 if (x % 3 == 0) { // 给第一个人发牌 weiweiList.add(array.get(x)); } else if (x % 3 == 1) { // 给第二个人发牌 minminList.add(array.get(x)); } else if (x % 3 == 2) { // 给第三个人发牌 guangtouList.add(array.get(x)); } } // 打印一下三个人手上的牌 System.out.println("weiweiList " + weiweiList); System.out.println("minminList " + minminList); System.out.println("guangtouList " + guangtouList); //看底牌 //由于前面发牌的动作只到集合的size()-3,所以剩下三张 //这三张牌,使用ArrayList的get(index)方法获取,那么下标应该从array.size()-3开始,到array.size() System.out.println("底牌是: "); for(int x=array.size()-3; x<array.size(); x++){ //打印底牌出来 System.out.print(array.get(x)+ " "); } System.out.println("要叫地主吗?"); } }
结果:
不分析了,大家看看哪一家会赢!!!
相关文章推荐
- Java基础-Exception
- java学习笔记——日期操作类(date,calendar等)
- Java URLClassLoader实现插件功能开发
- 谈谈java垃圾回收机制
- java学习笔记——String类
- java学习笔记——内部类
- java读XML文件
- 尚硅谷公开课--struts2--3--struts2中获取web资源的几种方式
- 【JAVA】接口(一)
- 深入理解java强大的注解
- 使用spring的jdbcTemplate-----用JDBC模板查询数据库
- jdk配置
- java中哈希表用途
- 爬虫 博客 增加访问量 Jsoup Java 正则 实现
- 计算Java List中的重复项出现次数【转】
- 理解Java ClassLoader机制(转载)
- Java实现排序算法之快速排序
- 动态加载与插件化
- java中String字符的替换
- javaweb1000例 (一)