学习笔记6
看的是黑马程序员的课,生动有趣,特别是最后的斗地主案例差点让我没绷住ww
集合
-
集合类的特点:提供一种存储空间可变的存储模型,存储的数据容量可以随时发生改变
-
集合类体系结构:单列数据存储称之为Collection集合,双列数据存储称之为Map集合
Collection集合中List集合里的数据可重复,Set集合里的数据不可重复
重点学习List集合下的ArrayList和LinkedList,Set集合下的HashSet和TreeSet,Map集合下的HashMap
-
Collection,Map,List,Set都是接口,剩下的都是实现类
一、 Collection集合
1. 概述
- 是单例集合的顶层接口,它表示一组对象,这些对象也称之为Collection的元素
- JDK不提供此接口的任何直接实现,它提供跟具体的子接口(如List和Set)实现
2. 创建Collection集合的对象
-
多态的方式
-
具体的实现类ArrayList
-
示例代码
package com.Collection.lesson01; import java.util.ArrayList; import java.util.Collection; //以多态的方式创建Collection集合的对象 public class Demo01 { public static void main(String[] args) { Collection<String> c = new ArrayList<>(); //添加元素: add(E e) c.add("hello"); c.add("world"); c.add("java"); //输出 System.out.println(c); } }
3. Collection集合常用方法
-
boolean add(E e)
//添加元素 -
boolean remove(Object o)
//从集合中移除指定的元素 -
void clear()
//清空集合中的元素 -
boolean contains(Object o)
//判断集合中是否存在指定的元素 -
boolean isEmpty()
//判断集合是否为空 -
int size()
//集合的长度,也就是集合中元素的个数 -
示例代码:
package com.Collection.lesson01; import java.util.ArrayList; import java.util.Collection; public class Demo02 { public static void main(String[] args) { //创建集合对象 Collection<String> c = new ArrayList<>(); //Alt + 7 查看项目结构 //boolean add(E e): 添加元素 System.out.println(c.add("hello")); System.out.println(c.add("world")); System.out.println(c.add("java"));//返回值为true c.add("hello"); c.add("world"); c.add("java"); System.out.println(c); System.out.println("===================="); //boolean remove(E e): 移除元素 System.out.println(c.remove("hello"));//从头开始移除,一次移除一个 System.out.println(c.remove("javaee")); c.remove("java"); System.out.println(c); System.out.println("===================="); //void clean(): 清空元素 c.clear(); System.out.println(c); System.out.println("===================="); //boolean contains(object o): 判断集合中是否有这个元素 System.out.println(c.contains("hello")); System.out.println("===================="); //boolean isEmpty(): 判断集合内是否为空 System.out.println(c.isEmpty()); System.out.println("===================="); //int size(): 集合的长度 System.out.println(c.size()); } }
4. Collection 集合的遍历
使用Iterator迭代器,集合的专用遍历方式
-
Iterator
iterator(): 返回此集合中元素的迭代器,通过集合的iterator()方法得到 -
迭代器是通过集合的iterator()方法得到的,所以我们说他是依赖于集合而存在的
-
示例代码:
package com.Collection.iterator; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class Demo01 { public static void main(String[] args) { Collection<String> c = new ArrayList<>(); c.add("hello"); c.add("world"); c.add("java"); //Iterator<E> iterator() 返回此集合中的迭代器,通过集合的iterator()方法得到 Iterator<String> iterator = c.iterator(); //E next(): 返回迭代的最后一个元素 /* System.out.println(iterator.next()); System.out.println(iterator.next()); System.out.println(iterator.next()); //System.out.println(iterator.next());//NoSuchElementException: 表示被请求的元素不存在 */ //boolean hasNext()方法判断迭代的最后一个是否存在 /* if(iterator.hasNext()){ System.out.println(iterator.next()); } if(iterator.hasNext()){ System.out.println(iterator.next()); } if(iterator.hasNext()){ System.out.println(iterator.next()); } if(iterator.hasNext()){ System.out.println(iterator.next()); } */ //循环遍历 while (iterator.hasNext()){ String s = iterator.next(); System.out.println(s); } } }
5. 集合的使用步骤
步骤1:创建集合对象
步骤2:添加元素
-
创建元素
-
添加元素到集合
合并为添加元素到集合
步骤3:遍历集合
- 通过集合对象获取迭代器对象
- 通过迭代器对象的hasNext() 方法判断是否还有元素
- 通过迭代器对象的next() 方法获取下一个元素
6. 案例:Collection集合存储
需求:创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历集合。
示例代码:
Student.java
package com.Collection.demo; 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 int getAge() { return age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } }
Demo.java
package com.Collection.demo; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class Demo { public static void main(String[] args) { Collection<Student> c = new ArrayList<Student>(); Student s1 = new Student("张三",21); Student s2 = new Student("李四",22); Student s3 = new Student("王五",20); //犯了个错误,忘了创建main方法 c.add(s1); c.add(s2); c.add(s3); //使用迭代器遍历集合 //这里要标一下<Student>, 要不然需要使用Object类强转 Iterator<Student> iterator = c.iterator(); while (iterator.hasNext()){ //使用一个学生对象来存放当前的学生元素 Student s = iterator.next(); System.out.println("学生的姓名为:" + s.getName() +"\t"+ "学生的年龄为:" + s.getAge()); } } }
二、List集合
1. 概述
- 是有序集合(也称为序列),用户可以精确控制列表中每个元素的插入位置。用户可以通过证书索引访问元素,并搜索列表中的元素
- 与Set集合不同,列表通常允许重复的元素
2. 特点
-
有序:存储和取出的元素顺序一致
-
可重复:存储的元素可以重复
-
示例代码:
Demo01.java
package com.list.lesson01; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Demo01 { public static void main(String[] args) { //创建一个集合对象 List<String> list = new ArrayList<>(); list.add("java1"); list.add("java2"); list.add("java3"); list.add("java3");//可重复 System.out.println(list); System.out.println("==============="); //采用迭代器的方式遍历list Iterator<String> iterator = list.iterator(); while (iterator.hasNext()){ String s = iterator.next(); System.out.println(s); } } }
3. List集合特有方法
-
void add(int index,E element)
:在此集合中的指定位置插入指定的元素 -
E remove(int index)
:删除指定索引处的元素,返回被删除的元素 -
E set(int index,E element)
:修改指定索引处的元素,返回被修改的元素 -
E get(int index)
:返回索引处的元素 -
示例代码:
Demo02.java
package com.list.lesson01; import java.util.ArrayList; import java.util.List; public class Demo02 { public static void main(String[] args) { //创建集合对象 List<String> list = new ArrayList<String>(); list.add("java01"); list.add("java02"); list.add("java03"); System.out.println(list); System.out.println("======================="); //boolean add(int index, E element )在指定位置插入元素 list.add(1,"java04"); //list.add(11,"java05"); //IndexOutOfBoundsException System.out.println(list); System.out.println("======================="); //boolean remove(): 移除指定位置元素 list.remove(1); System.out.println(list); System.out.println("======================="); //E set(int index, E element ): 修改指定索引处的元素,返回被修改的元素 System.out.println(list.set(1, "java04")); System.out.println(list); System.out.println("======================="); //E get(int index ): 返回指定索引的元素 System.out.println(list.get(1)); System.out.println(list); System.out.println("======================="); //通过索引遍历集合 for (int i = 0; i < list.size(); i++) { String s = list.get(i); System.out.println(s); } } } *注意索引越界异常!!
4. 案例
创建一个存储学生对象的集合,存储3个学生对象,使用程序实现在控制台遍历该集合
示例代码:
Student.java同上
Demo03.java
package com.list.lesson01; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class Demo03 { public static void main(String[] args) { //创建集合类 List<Student> list = new ArrayList<>(); //创建学生类 Student s1 = new Student("张三",21); Student s2 = new Student("李四",22); Student s3 = new Student("王五",20); //存储学生类 list.add(s1); list.add(s2); list.add(s3); //遍历学生类 迭代器方式 Iterator<Student> iterator = list.iterator(); while (iterator.hasNext()){ Student s = new Student(); s = iterator.next(); System.out.println("学生姓名为:"+s.getName()+"\t" + "学生年龄为:" + s.getAge()); } System.out.println("========================"); //遍历学生类 for循环 for (int i = 0; i < list.size(); i++) { Student s = new Student(); s = list.get(i); System.out.println("学生姓名为:"+s.getName()+"\t" + "学生年龄为:" + s.getAge()); } //遍历学生类 增强for循环 for (Student s : list) { System.out.println("学生姓名为:"+s.getName()+"\t" + "学生年龄为:" + s.getAge()); } } }
5. 并发修改异常
- ConcurrentModificationException
- 产生原因:迭代器遍历的过程中,通过集合对象修改了集合中元素的长度,造成了迭代器获取元素中判断预期修改值和实际修改值不一致
- 解决方案:1. 用for循环遍历(可以在循环体里面直接添加)2. 迭代器遍历中只判断不添加,在循环体外再添加(是我一开始想的,然后没有遇到这个异常)
6. ListIterator 列表迭代器
-
通过List集合的listIterator() 方法得到,所以说它是List集合特有的迭代器
-
用于允许程序员沿着任一方向遍历列表的列表迭代器,在迭代期间修改列表,并获取列表中迭代器的当前位置
-
常用方法
E next()
:返回迭代中的下一个元素boolean hasNext()
:如果迭代具有更多元素,则返回trueE previous()
:返回列表中的上一个元素boolean hasPrevious()
:如果此列表迭代器在相反方向遍历列表是具有更多元素,则返回truevoid add(E e)
:将指定的元素插入列表
-
示例代码:
ListIteratorDemo.java
package com.list.lesson01; import java.util.ArrayList; import java.util.List; import java.util.ListIterator; public class ListIteratorDemo { public static void main(String[] args) { //创建一个集合对象 List<String> list = new ArrayList<>(); list.add("java1"); list.add("java2"); list.add("java3"); ListIterator<String> listIterator = list.listIterator(); while (listIterator.hasNext()){ String s = listIterator.next(); System.out.println(s); } System.out.println("======================"); while (listIterator.hasPrevious()){ String s = listIterator.previous(); System.out.println(s); } System.out.println("======================"); //获取列表迭代器 while (listIterator.hasNext()){ String s = listIterator.next(); if (s.equals("java1")){ listIterator.add("java0");//在当前迭代的地方加上元素 } } System.out.println(list); } }
7. 增强for循环
- 实现Iterator接口的类允许其对想成为增强型for语句的目标
- 它是JDK5之后出现的,其内部原理是一个Iterator迭代器
- 已经在java基础里面学过,这里大致掠过
8. 常见数据结构:栈-队列-数组-链表
- 栈
- 数据进入栈模型的过程称为:压/进栈
- 数据离开栈模型的过程称为:弹/出栈
- 先进后出
- 队列
- 数据从后端进入队列模型的过程成为:入队列
- 数据从前端离开队列模型的过程称为:出队列
- 先进先出
- 数组
- 查询效率高,删除效率低
- 链表
- 增删快,查询效率低
9. LIst集合子类特点
- ArrayList:底层数据结构是数组,查询快,增删慢
- LinkedList:底层数据结构是链表,查询快,增删慢
练习:分别使用ArrayList‘和LinkedList遍历字符串
package com.list.lesson01; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedList; import java.util.List; public class Demo05 { public static void main(String[] args) { //创建一个集合对象 ArrayList<String> list1 = new ArrayList<>(); list1.add("java1"); list1.add("java2"); list1.add("java3"); //遍历 for (String s : list1){ System.out.println(s); } System.out.println("=================="); for (int i = 0; i < list1.size(); i++) { String s = list1.get(i); System.out.println(s); } System.out.println("=================="); Iterator<String> iterator = list1.iterator(); while (iterator.hasNext()){ String s = iterator.next(); System.out.println(s); } System.out.println("=================="); //创建一个集合对象 LinkedList<String> list2 = new LinkedList<>(); list2.add("java1"); list2.add("java2"); list2.add("java3"); //注意自动补齐的是否是你需要的 Iterator<String> iterator1 = list2.iterator(); while (iterator1.hasNext()){ String s = iterator1.next(); System.out.println(s); } System.out.println("=================="); for (String s : list2){ System.out.println(s); } System.out.println("=================="); for (int i = 0; i < list2.size(); i++) { String s = list2.get(i); System.out.println(s); } } }
10. LinkedList集合的特有功能
public void addFirst(E e)
:在该列表开头插入指定的元素public void addLast(E e)
:在该列表末尾插入指定的元素public E getFirst()
:返回此列表的第一个元素public E getLast()
:返回此列表的最后一个元素public E removeFirst()
:从此列表删除并返回最后一个元素public E removeLast()
:从此列表删除并返回最后一个元素- 示例代码:
package com.list.lesson01; import java.util.LinkedList; public class Demo06 { public static void main(String[] args) { LinkedList<String> linkedList = new LinkedList<>(); linkedList.add("hello"); linkedList.add("world"); linkedList.add("java"); //public void addFirst(E e):在该列表开头插入指定的元素 linkedList.addFirst("javase"); System.out.println(linkedList); System.out.println("================="); //public void addLast(E e):在该列表末尾插入指定的元素 linkedList.addLast("javaee"); System.out.println(linkedList); System.out.println("================="); //public E getFirst():返回此列表的第一个元素 System.out.println(linkedList.getFirst()); System.out.println("================="); //public E getLast():返回此列表的最后一个元素 System.out.println(linkedList.getLast()); System.out.println("================="); //public E removeFirst():删除此列表的一个元素并返回第一个元素 System.out.println(linkedList.removeFirst()); System.out.println(linkedList); System.out.println("================="); //public E removeLast():删除此列表的最后一个元素并返回最后一个元素 System.out.println(linkedList.removeLast()); System.out.println(linkedList); System.out.println("=================");
三、Set集合
1. 特点
- 不包含重复元素的集合
- 没有带索引的方法,所有不能使用普通for循环遍历
- 存储字符串并遍历,示例代码:
package com.collection.set; import java.util.HashSet; import java.util.Iterator; import java.util.Set; public class SetDemo01 { public static void main(String[] args) { //创建集合对象 //Hashset: 对集合的迭代顺序不作任何保证 Set<String> set = new HashSet<String>(); //添加元素 set.add("hello"); set.add("world"); set.add("java"); set.add("java"); //增强for for (String s : set){ System.out.println(s); }/* world java hello 无重复元素 */ //迭代器方式 Iterator<String> it = set.iterator(); while (it.hasNext()){ String s = it.next(); System.out.println(s); } } }
2. 哈希值
是JDK根据对象的地址或者字符串或者数字算出来的int类型的数值
Object类中有一个方法可以获取对象的哈希值
- public int hashCode(): 返回对象的哈希码值
- 示例代码:
package com.collection.set; import java.util.HashSet; import java.util.Set; public class HashDemo01 { public static void main(String[] args) { //创建对象 Set<Student> set = new HashSet<Student>(); Student s1 = new Student("张三",23); Student s2 = new Student("李四",24); Student s3 = new Student("王五",25); //获取哈希值 System.out.println(s1.hashCode()); //460141958 //多次调用hashCode()哈希值是相同的 //System.out.println(s1.hashCode()); //460141958 //默认情况下,不同对象的哈希值是不相同的 //通过方法重写可以实现相同的哈希值 System.out.println(s2.hashCode()); //1163157884 System.out.println(s3.hashCode()); //1956725890 //String 方法重写了hashCode方法 System.out.println("重地".hashCode()); //1179395 System.out.println("通话".hashCode()); //1179395 } }
3. HashSet集合概述和特点
HashSet集合特点
- 底层数据结构是哈希表
- 对集合的迭代顺序不做任何保证,也就是说不保证存储和取出的元素顺序一致
- 没有带索引的方法,所以不能使用普通for循环遍历
- 由于是Set集合,所以是不包含重复元素的集合
练习
- 存储字符串并遍历
- 示例代码:
package com.collection.set; import java.util.HashSet; import java.util.Iterator; public class HashSetDemo01 { public static void main(String[] args) { //创建对象 HashSet<String> hs = new HashSet<>(); //添加元素 hs.add("hello"); hs.add("world"); hs.add("java"); //增强for遍历 for (String s : hs){ System.out.println(s); } //迭代器遍历 Iterator<String> it = hs.iterator(); while (it.hasNext()){ String s = it.next(); System.out.println(s); } } }
4. HashSet集合保证元素唯一性源码分析
HashSet集合添加一个元素的过程:
- 调用对象的hashCode()方法获取对象的哈希值
- 根据对象的哈希值计算对象的存储位置
- 判断该位置是否有元素存在
- 如果没有元素则将元素存储到该位置
- 如果有则遍历该位置的所有元素,与新存入的元素比较哈希值是否相同
- 都不相同则将元素存储到该位置
- 有相同的则调用equals方法比较对象内容是否相同
- 返回false则将元素存储到该位置
- 返回true则说明元素重复,不进行存储
HashSet集合存储元素:
- 要保证元素唯一性,需要重写hashCode()和equals()
5. 常见数据结构:哈希表
- JDK8之前,底层采用数组+链表实现,可以说是一个元素为链表的数组(数组长度默认为16)
- JDK8以后,在长度比较长的时候,底层实现了优化
6. 案例:HashSet集合存储学生对象并遍历
需求:创建一个存储学生对象的的集合,存储多个学生对象,使用程序实现在控制台遍历该集合
要求:学生对象的成员变量值相同,我们就认为是同一个对象
注意:Student类需要重写hashCode()和equals()方法,否则不能完成需求。重写在IDEA中可以直接使用快捷键Alt + Insert一键生成
示例代码:
package com.collection.set; import java.util.Objects; 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 int getAge() { return age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return age == student.age && Objects.equals(name, student.name); } @Override public int hashCode() { return Objects.hash(name, age); } }
package com.collection.set; import java.util.HashSet; import java.util.Iterator; public class HashSetDemo01 { public static void main(String[] args) { //创建对象 HashSet<String> hs = new HashSet<>(); //添加元素 hs.add("hello"); hs.add("world"); hs.add("java"); //增强for遍历 for (String s : hs){ System.out.println(s); } //迭代器遍历 Iterator<String> it = hs.iterator(); while (it.hasNext()){ String s = it.next(); System.out.println(s); } } }
7. LinkedHashSet集合概述和特点
LinkedHashSet集合特点
- 哈希表和链表实现的Set接口,具有可预测的迭代次数
- 由链表保证元素有序,也就是说元素的存储和取出顺序是一致的
- 由哈希表保证元素唯一,也就是说没有重复的元素
LinkedHashSet集合练习
- 存储字符串并遍历
- 示例代码如下:
package com.collection.set; import java.util.Iterator; import java.util.LinkedHashSet; public class LinkedHashSetDemo01 { public static void main(String[] args) { //创建集合对象 LinkedHashSet<String> lhs = new LinkedHashSet<>(); lhs.add("hello"); lhs.add("world"); lhs.add("java"); //遍历集合 增强for for (String s : lhs){ System.out.println(s); } System.out.println("================="); //遍历集合 迭代器 Iterator<String> it = lhs.iterator(); while (it.hasNext()){ String s = it.next(); System.out.println(s); } } }
8. TreeSet集合概述和特点
- 元素有序,这里的顺序不是指存储和取出的顺序,而是按照一定的规则进行排序,具体排序方式取决于构造方法
- TreeSet():根据其元素的自然排序进行排序
- TreeSet(Comparator comparator):根据指定的比较器进行排序
- 没有带索引的方法,所以不包含重复元素的集合
- 由于是Set集合,所以不包含重复元素的集合
练习
- 存储整数并遍历
- 示例代码
package com.collection.set; import java.util.TreeSet; public class TreeSetDemo01 { public static void main(String[] args) { //创建集合对象 String类型 TreeSet<String> ts = new TreeSet<>(); //添加元素 ts.add("hello"); ts.add("world"); ts.add("java"); //遍历集合 增强for for (String s : ts){ System.out.println(s); } //创建集合对象 int类型 //只能用引用类型 //TreeSet<int> ints = new TreeSet<int>(); TreeSet<Integer> ints = new TreeSet<>(); //添加元素 ints.add(10); ints.add(9); ints.add(167); //遍历集合 增强for for (int i : ints){ System.out.println(i);//会从小到大排序//自然排序 } } }
9. 自然排序Comparable的使用
- 存储学生对象并遍历,创建TreeSet集合使用无参构造方法
- 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
- 示例代码
package com.collection.set; import java.util.Objects; 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 int getAge() { return age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return age == student.age && Objects.equals(name, student.name); } @Override public int hashCode() { return Objects.hash(name, age); } @Override public int compareTo(Student s) { // return 0; // return 1; // //当前是这一个 int num = this.age - s.age;//传入的是前一个 // return num;//大于0就放后面,小于0就放前面 //年龄相同时,按照姓名规则 int num2 = num == 0 ? this.name.compareTo(s.name) : num; return num2; } }
package com.collection.set; import java.util.TreeSet; public class TreeSetDemo02 { public static void main(String[] args) { //创建集合对象 TreeSet<Student> ts = new TreeSet<>(); //创建学生对象 Student s1 = new Student("ZhangSan",23); Student s2 = new Student("LiSi",24); Student s3 = new Student("WangWu",25); Student s4 = new Student("LiuLu",21); Student s5 = new Student("QianQi",24); //添加元素 ts.add(s1); ts.add(s2); ts.add(s3); ts.add(s4); ts.add(s5); //遍历集合 增强for for (Student s : ts){ System.out.println("姓名为:" + s.getName() + "\t" + "年龄为:" + s.getAge()); } } }
结论:
-
用TreeSet集合存储自定义对象,无参构造方法使用的是自然排序对元素进行排序的
-
自然排序,就是让元素所属的类实现Comparable接口,重写Compareto(T o)方法
-
重写方法时,一定要注意排序规则必须按照要求的主要条件和次要条件来写
10. 比较器排序Comparator的使用
- 存储学生对象并遍历,创建TreeSet集合使用带参构造方法
- 要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
- 示例代码
package com.collection.set; import java.util.Objects; 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 int getAge() { return age; } public void setName(String name) { this.name = name; } public void setAge(int age) { this.age = age; } }
package com.collection.set; import java.util.Comparator; import java.util.TreeSet; public class TreeSetDemo03 { public static void main(String[] args) { //创建集合对象 TreeSet<Student> ts = new TreeSet<>(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("张三", 23); Student s2 = new Student("李四", 24); Student s3 = new Student("王五", 25); Student s4 = new Student("刘陆", 23); //添加元素 ts.add(s1); ts.add(s2); ts.add(s3); ts.add(s4); //遍历集合 for (Student s : ts){ System.out.println("姓名为:" + s.getName() + "\t" + "年龄为:" + s.getAge()); } } }
11. 案例:成绩排序
需求:用TreeSet集合存储多个学生信息(姓名,语文成绩,数学成绩),并遍历该集合
要求:按照总分从高到低出现
示例代码:
package com.collection.set; public class StudentMassage { private String name; private int chinese; private int math; public StudentMassage() { } public StudentMassage(String name, int chinese, int math) { this.name = name; this.chinese = chinese; this.math = math; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getChinese() { return chinese; } public void setChinese(int chinese) { this.chinese = chinese; } public int getMath() { return math; } public void setMath(int math) { this.math = math; } public int getSum(){ int sum = this.chinese + this.math; return sum; } }
package com.collection.set; import java.util.Comparator; import java.util.TreeSet; public class TreeSetDemp04 { public static void main(String[] args) { //创建集合对象 //有参 TreeSet<StudentMassage> ts = new TreeSet<StudentMassage>(new Comparator<StudentMassage>() { @Override public int compare(StudentMassage s1, StudentMassage s2) { int sum = s1.getSum() - s2.getSum(); int num = sum == 0 ? s1.getName().compareTo(s2.getName()) : sum; return num; } }) ; //创建学生信息对象 StudentMassage s1 = new StudentMassage("张三", 90, 91); StudentMassage s2 = new StudentMassage("李四", 78, 76); StudentMassage s3 = new StudentMassage("王麻子", 60, 100); StudentMassage s4 = new StudentMassage("刘小菜", 98, 99); StudentMassage s5 = new StudentMassage("陈大荣", 99, 98); //添加学生对象至集合 ts.add(s1); ts.add(s2); ts.add(s3); ts.add(s4); ts.add(s5); //遍历集合 for (StudentMassage s : ts){ System.out.println("姓名:" + s.getName() + "\t" + "语文成绩:" + s.getChinese() + "\t" + "数学成绩:" + s.getMath() + "\t" + "总分:" + s.getSum() ); } } }
12. 案例:不重复的随机数
需求:编写一个程序,获取10个1-20之间的随机数,要求随机数不能重复,并在控制台输出
示例代码:
package com.collection.set; import java.util.HashSet; import java.util.Random; import java.util.Set; public class RadnomSetDemo01 { public static void main(String[] args) { //创建集合对象 //无序 Set<Integer> set = new HashSet<>(); //有序 //Set<Integer> set = new TreeSet<>(); //创建随机数对象 Random r = new Random(); //添加随机数至集合 while(set.size()<10){ set.add(r.nextInt(20)+1); } //遍历数组 for (int i : set){ System.out.println(i); } } }
四、泛型
1. 泛型概述
泛型是JDK5中引入的特性,它提供了编译时类型安全监测机制,该机制允许在编译时检测到非法的
类型,它的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数
一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参,那么参数化类型怎么
理解呢?顾名思义,就是将类型由原来的具体的类型参数化,然后在使用/调用时传入具体的类型
这种类型可以用在类、方法和接口中,分别被称为泛型类、泛型方法和泛型接口
泛型定义格式:
- <类型>:指定一种类型的格式,这里的类型可以看成是形参
- <类型1, 类型2>:指定多种类型的格式,多种类型之间用逗号隔开。这里的类型可以看成是形参
- 将来具体调用的时候给定的类型可以看成是实参,并且实参的类型只能是引用数据类型
示例代码:
package com.collection.generic; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; public class GenericDemo { public static void main(String[] args) { //创建集合对象 Collection<String> c = new ArrayList<String>(); //添加元素 c.add("hello"); c.add("world"); c.add("java"); // c.add(100);//ClassCastException //遍历 // Iterator it = c.iterator(); Iterator<String> it = c.iterator(); while (it.hasNext()){ // Object obj = it.next(); // System.out.println(obj); // String s = (String) it.next(); String s = it.next(); System.out.println(s); } } }
范型的好处:
- 把运行时期的问题提前到了编译期间
- 避免了强制类型转换
2. 泛型类
泛型类的定义格式:
- 格式:修饰符 class 类名<>{}
- 示例:public class Generic<>{}
- 示例代码:
package com.collection.generic; public class Student { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } }
package com.collection.generic; public class Teacher { public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } private Integer age; }
package com.collection.generic; public class Generic<T> { private T t; public T getT() { return t; } public void setT(T t) { this.t = t; } }
package com.collection.generic; public class GenericDemo02 { public static void main(String[] args) { //创建学生对象 Student s1 = new Student(); s1.setName("张三"); //创建老师对象 Teacher t1 = new Teacher(); t1.setAge(30); System.out.println(s1.getName()); System.out.println(t1.getAge()); System.out.println("============="); //创建泛型对象 Generic<String> g1 = new Generic<>(); g1.setT("张麻子"); Generic<Integer> g2 = new Generic<>(); g2.setT(32); Generic<Boolean> g3 = new Generic<>(); g3.setT(true); System.out.println(g1.getT()); System.out.println(g2.getT()); System.out.println(g3.getT()); } }
3. 泛型方法
泛型方法的定义格式:
- 格式:修饰符 <类型> void show(T t){}
- 范例:public
void show(T t){} - 示例代码:
package com.collection.generic; //public class Generic2<T> { // public void show (String s){ // System.out.println(s); // } // public void show (Integer i){ // System.out.println(i); // } // public void show (Boolean b){ // System.out.println(b); // } //泛型类改进 // public void show (T t){ // System.out.println(t); // } //泛型方法改进 public class Generic2{ public <T> void show (T t){ System.out.println(t); } }
package com.collection.generic; public class GenericDemo03 { public static void main(String[] args) { // //创建泛型对象 // Generic2 g1 = new Generic2(); // g1.show("String"); // g1.show(100); // g1.show(false); //泛型类改进 // Generic2<String> g1 = new Generic2<String>(); // g1.show("String"); // Generic2<Integer> g2 = new Generic2<Integer>(); // g2.show(100); // Generic2<Boolean> g3 = new Generic2<Boolean>(); // g3.show(false); //泛型方法改进 Generic2 g1 = new Generic2(); g1.show("String"); Generic2 g2 = new Generic2(); g2.show(100); Generic2 g3 = new Generic2(); g2.show(false); } }
4. 泛型接口
泛型接口的定义格式:
- 格式:修饰符 interface 接口名<类型>{}
- 范例:public interface Generic
{} - 示例代码:
package com.collection.generic; public interface Generic3<T> { void show(T t); }
package com.collection.generic; public class GenericImpl<T> implements Generic3<T> { @Override public void show(T t) { System.out.println(t); } }
package com.collection.generic; public class GenericDemo04 { public static void main(String[] args) { GenericImpl<String> g1 = new GenericImpl<>(); GenericImpl<Integer> g2 = new GenericImpl<>(); GenericImpl<Boolean> g3 = new GenericImpl<>(); g1.show("String"); g2.show(100); g3.show(false); } }
5. 类型通配符
为了表现各种泛型List的父类,可以使用类型通配符
- 类型通配符:<?>
- List<?>:表示元素类型未知的List,它的元素可以匹配任何的类型
- 这种带通配符的List仅表示它是各种泛型List的父亲,并不能把元素添加到其中
如果我们不希望List<?>时任何泛型List的父类,只希望它代表某一类泛型List的父亲,可以使用类型通配符的上限
- 类型通配符上限:<? extends 类型>
- :它表示的类型是**Number或者其子类型**
除了可以指定类型通配符的上限,我们也可以指定类型通配符的下限
- 类型通配符下限:<? super 类型>
- List<? super Number>:它表示的类型是Number或者其父类型
示例代码:
package com.collection.generic; import java.util.ArrayList; import java.util.List; public class GenericDemo05 { public static void main(String[] args) { //类型通配符: <?> List<?> list1 = new ArrayList<Object>(); List<?> list2 = new ArrayList<Number>(); List<?> list3 = new ArrayList<Integer>(); //类型通配符上限:<? extends 类型> //List<? extends Number> list4 = new ArrayList<Object>(); List<? extends Number> list4 = new ArrayList<Integer>(); //类型通配符下限:<? super 类型> //List<? super Number> list5 = new ArrayList<Integer>(); List<? super Number> list5 = new ArrayList<Object>(); } }
6. 可变参数的使用
可变参数在前面的java方法中已经学过一部分
Arrays工具类中有一个静态方法:
- public static
List asList(T... a):返回由指定数组支持的固定大小的列表
//下面都是JDK9才新增的,我目前是JDK8,我说怎么一直报错,原来我没有。。。
List接口中有一个静态方法:
- public static
List of(E... elements):返回包含任意数量元素的不可变列表
Set接口中有一个静态方法:
- public static
Set of(E... elements):返回一个包含任意数量元素的不可变集合
五、Map集合
1.Map集合概述和使用
概述:
- Interface Map<K,V> k:键的类型 V:值的类型
- 将键映射到值的对象;不能包含重复的键;每个键可以映射到最多一个值
- 举例:学生的学号和姓名
- zj001 张三
- zj002 李四
- zj003 王麻子
- 示例代码:
package com.collection.map; import java.util.HashMap; import java.util.Map; public class MapDemo01 { public static void main(String[] args) { //创建Map对象 Map<String, String> map = new HashMap<>(); //添加元素 map.put("zj001","张三"); map.put("zj002","李四"); map.put("zj003","王麻子"); //第二次出现的键是用来修改元素 map.put("zj003","钱七"); System.out.println(map); } }
2. Mapj集合的基本功能
V put(K key, V value)
:添加元素V remove(K key)
:根据键删除键值对应元素boolean containsKey(K key)
:判断集合是否包含指定的键boolean containsValue(V value)
:判断集合是否包含指定的值int size()
:集合的长度,即集合中键值对的个数void clear()
:清除集合内所有元素boolean isEmpty()
:判断集合是否为空
示例代码:
package com.collection.map; import java.util.HashMap; import java.util.HashSet; import java.util.Map; public class MapDemo02 { public static void main(String[] args) { //创建集合对象 Map<String, String> map = new HashMap<>(); //添加集合元素 //V put(K key, V value) map.put("林丹","李宗伟"); map.put("谌龙","安赛龙"); map.put("石宇奇","桃田贤斗"); System.out.println(map); System.out.println("================"); //移除元素 //V remove(K key) System.out.println(map.remove("石宇奇"));//返回键对应的值 System.out.println(map.remove("金庭")); System.out.println(map); System.out.println("================"); //判断键是否存在 //boolean containsKey(K key) System.out.println(map.containsKey("谌龙")); System.out.println("================"); //判断值是否存在 //boolean containsValue(V value) System.out.println(map.containsValue("安赛龙")); System.out.println("================"); //集合的长度 //int size() System.out.println(map.size()); System.out.println("================"); //清除所有元素 //void clear() map.clear(); System.out.println(map); System.out.println("================"); //判断集合是否为空 //boolean isEmpty() System.out.println(map.isEmpty()); } }
3. Map集合的获取功能
-
V get(Object key)
:根据键获取值 -
Set<K> keySet()
:获取所有键的集合 -
Collection<V> Values()
:获取所有值的集合 -
示例代码:
package com.collection.map; import java.util.*; public class MapDemo03 { public static void main(String[] args) { //创建集合元素 Map<String,String> map = new HashMap<String,String>(); //添加元素 map.put("林丹","李宗伟"); map.put("谌龙","安赛龙"); map.put("石宇奇","桃田贤斗"); //V get(Object key):根据键获取值 System.out.println(map.get("林丹")); System.out.println(map.get("谌龙")); System.out.println(map.get("石宇奇")); System.out.println("================="); //Set<K> keySet():获取所有键的集合 Set<String> set = map.keySet(); for (String s : set){ System.out.println(s); } System.out.println("=================="); //Collection<V> Values():获取所有值的集合 Collection<String> co = map.values(); for (String s : co){ System.out.println(s); } } }
4. Map集合的遍历
-
方式一:
- 先获取所有的键 Set
- 再通过键寻找值 get
- 示例代码:
package com.collection.map; import java.util.HashMap; import java.util.Map; import java.util.Set; public class MapDemo04_1 { public static void main(String[] args) { //创建集合元素 Map<String,String> map = new HashMap<String,String>(); //添加元素 map.put("林丹","李宗伟"); map.put("谌龙","安赛龙"); map.put("石宇奇","桃田贤斗"); //先获取键的Set集合 Set<String> set = map.keySet(); //再用增强for遍历键的Set集合 for (String s1 : set){ //找出每个键对应的值get String s2 = map.get(s1); System.out.println(s1 + "," +s2); }//无序 } } -
方式二
- 获取所有键值对对象的集合
- Set<Map.Entry<K,V>> entrySet():获取所有键值对对象的集合
- 遍历键值对对象的集合,得到每一个键值对对象
- 用增强for实现,得到每一个Map.Entry
- 示例代码
package com.collection.map; import java.util.HashMap; import java.util.Map; import java.util.Set; public class MapDemo04_2 { public static void main(String[] args) { //创建集合元素 Map<String,String> map = new HashMap<String,String>(); //添加元素 map.put("林丹","李宗伟"); map.put("谌龙","安赛龙"); map.put("石宇奇","桃田贤斗"); //获取所有键值对对象的集合 Set<Map.Entry<String,String>> set = map.entrySet(); //遍历键值对对象的集合 for (Map.Entry<String,String> e : set){ String s1 = e.getKey(); String s2 = e.getValue(); System.out.println(s1+","+s2); } } } - 获取所有键值对对象的集合
5. 案例:HashMap集合存储学生对象并遍历
- 需求:创建一个HashMap集合,键是学号(String),值使学生对象(Student)。存储三个键值对元素,并遍历。
- 示例代码
package com.collection.map; public class Student { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public Student() { } 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; } }
package com.collection.map; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; public class MapDemo05 { public static void main(String[] args) { //创建Map集合,键为学号(String),值为学生类 Map<String,Student> map = new HashMap<String,Student>(); //创建学生对象 Student s1 = new Student("张三", 23); Student s2 = new Student("李四", 24); Student s3 = new Student("王麻子", 25); //添加元素 map.put("113",s1); map.put("114",s2); map.put("115",s3); //遍历:键值对方式 //获取键值对 Set<Map.Entry<String, Student>> en = map.entrySet(); //遍历键值对 for (Map.Entry<String, Student> e : en){ Student s = e.getValue(); String name = s.getName(); int age = s.getAge(); String num = e.getKey(); System.out.println("学号为:" + num + "\t" + "姓名:" +name + "\t" + "年龄:" + age); } System.out.println("===================="); //直接获取键 //获取键的set集合 Set<String> set = map.keySet(); for (String num : set){ //通过键获得值 Student s = map.get(num); String name = s.getName(); int age = s.getAge(); System.out.println("学号为:" + num + "\t" + "姓名:" +name + "\t" + "年龄:" + age); } } }
-
需求:创建一个HashMap集合,键是学生对象(Student),值是居住地,存储多个键值对元素,并遍历。要求保证键的唯一性,如果学生对象的成员变量值相同,我们就认为是同一对象。
- 注意:要在上述学生类中重写hashCode() 和equals()
示例代码:
package com.collection.map; import java.util.Objects; public class Student { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public Student() { } 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 boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return age == student.age && Objects.equals(name, student.name); } @Override public int hashCode() { return Objects.hash(name, age); } }
package com.collection.map; import java.util.HashMap; import java.util.Map; import java.util.Set; public class MapDemo05_2 { public static void main(String[] args) { //创建Map集合对象 Map<Student, String> map = new HashMap<>(); //创建学生对象 Student s1 = new Student("张三", 23); Student s2 = new Student("李四", 24); Student s3 = new Student("王麻子", 25); Student s4 = new Student("王麻子", 25); //添加元素 map.put(s1,"北京"); map.put(s2,"上海"); map.put(s3,"广州"); map.put(s4,"南京"); //键值对遍历 Set<Map.Entry<Student, String>> en = map.entrySet(); for (Map.Entry<Student,String> e : en){ Student s = e.getKey(); String address = e.getValue(); String name = s.getName(); int age = s.getAge(); System.out.println("姓名:" +name + "\t" + "年龄:" + age + "\t" + "住址:" + address); } } }
6. 案例:ArrayList集合存储HashMap元素并遍历
需求:创建一个ArraysList集合,存储三个元素,每一个元素都是HashMap,每一个HashMap的键和值都是String,并遍历。
示例代码:
package com.collection.map; import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.Set; public class MapDemo06 { public static void main(String[] args) { //创建ArrayList集合 ArrayList<HashMap<String,String>> al = new ArrayList<HashMap<String,String>>(); //创建HashMap集合 HashMap<String, String> h1 = new HashMap<>(); HashMap<String, String> h2 = new HashMap<>(); HashMap<String, String> h3 = new HashMap<>(); //添加HashMap中的元素 h1.put("陈雨菲","山口茜"); h1.put("何冰娇","马琳"); h1.put("昆拉武特","奈良冈"); h2.put("石宇奇","桃田"); h2.put("林丹","李宗伟"); h2.put("骆建佑","李梓嘉"); h3.put("强贪壶","交闪"); h3.put("陨石","霍普"); h3.put("灰","G"); //添加ArrayList中的元素 al.add(h1); al.add(h2); al.add(h3); //遍历ArrayList集合 for (HashMap<String,String> h : al){ //遍历HashMap集合 Set<Map.Entry<String, String>> en = h.entrySet(); for (Map.Entry<String,String> e : en){ String key = e.getKey(); String value = e.getValue(); System.out.println(key + "," + value); } System.out.println("================="); } } }
7. 案例:HashMap集合存储ArrayList元素并遍历
需求:创建一个HashMap集合,存储三个键值对元素,每一个键值对元素的键是String,值是ArrayList,每一个ArrayList的元素是String,并遍历。
示例代码:
package com.collection.map; import java.util.ArrayList; import java.util.HashMap; import java.util.Set; public class MapDemo07 { public static void main(String[] args) { //创建HashMap集合对象 HashMap<String, ArrayList<String>> map = new HashMap<String, ArrayList<String>>(); //创建ArrayList集合对象 ArrayList<String> array1 = new ArrayList<>(); ArrayList<String> array2 = new ArrayList<>(); ArrayList<String> array3 = new ArrayList<>(); //添加ArrayList的元素 array1.add("天地玄黄"); array1.add("宇宙洪荒"); array2.add("上善若水"); array2.add("善利万物而不争"); array3.add("天行健"); array3.add("君子以自强不息"); //添加HashMap的元素 map.put("《千字文》",array1); map.put("《道德经》",array2); map.put("《周易》",array3); //遍历 Set<String> key = map.keySet(); for (String s : key){ System.out.println(s); for (String s1 : map.get(s) ){ System.out.println(s1); } System.out.println(); } } }
8. 案例:统计字符串中每个字符出现的次数
需求:键盘录入一个字符串,要求统计字符串中每个字符串出现的次数。
举例:键盘录入”aababcabcdabcde“ 在控制台输出:”a(5)b(4)c(3)d(2)e(1)“
示例代码:
package com.collection.map; import java.util.HashMap; import java.util.Scanner; import java.util.Set; public class MapDemo08 { public static void main(String[] args) { //创建HashMap集合对象 HashMap<Character, Integer> map = new HashMap<>(); //创建Scanner对象 Scanner scanner = new Scanner(System.in); System.out.println("请输入一个字符串:"); String s = scanner.nextLine(); //遍历字符串 for (int i = 0 ; i < s.length() ; i ++ ){ char c = s.charAt(i); /* //遍历HashMap集合 Set<Character> characters = map.keySet(); for (char key : characters ){ if (key == c){ //键相等则值加一 int value = map.get(key) + 1; map.put(c,value); flag = false; break; } }*/ //可以直接寻找 Integer v = map.get(c); if (v == null){ //没有相同的则添加 int value = 1; map.put(c,value); } else { //有相同的加1 Integer value = map.get(c) + 1; map.put(c,value); } } System.out.println(map); //拼接用StringBuilder StringBuilder sb = new StringBuilder(); //遍历HashMap集合 Set<Character> keySet = map.keySet(); for (Character key : keySet){ Integer value = map.get(key); sb.append(key).append("(").append(value).append(")"); } System.out.println(sb); } }
- 注意:如果想要让键进行自然排序可以使用TreeMap集合
六、Collections
1.Collections概述和使用
-
概述
- 是针对集合操作的工具类
-
常用方法
-
public static <T extends Comparable <? super T>> void sort(List <T> List)
:将指定的列表按升序排列 -
public static void reverse(List<?> list)
:反转指定列表中元素的顺序 -
public static void shuffle(List<?> list)
:使用默认的随机源随机排列指定的列表
-
-
示例代码
package com.collection.collections; import java.util.ArrayList; import java.util.Collections; public class CollectionsDemo01 { public static void main(String[] args) { //创建集合对象 ArrayList<Integer> list = new ArrayList<>(); //添加元素 list.add(12); list.add(201); list.add(32); list.add(-1); list.add(100); //输出 System.out.println(list); System.out.println("================="); //排序 Collections.sort(list); System.out.println(list); System.out.println("=================="); //反转 Collections.reverse(list); System.out.println(list); System.out.println("=================="); //随机 Collections.shuffle(list); System.out.println(list); System.out.println("=================="); } }
2. 案例:ArrayList存储学生对象并排序
需求:ArrayList存储学生对象,使用Collections对ArrayList进行排序
要求:按照年龄从小到大排序,年龄相同时,按照姓名的字母顺序排序
示例代码:
package com.collection.collections; public class Student { private String name; private int age; public Student(String name, int age) { this.name = name; this.age = age; } public Student() { } 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; } }
package com.collection.collections; import java.sql.Array; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; public class CollectionsDemo02 { public static void main(String[] args) { //创建集合对象 ArrayList<Student> list = new ArrayList<>(); //创建学生对象 Student s1 = new Student("zhangsan", 23); Student s2 = new Student("lisi", 24); Student s3 = new Student("wangmazi", 25); Student s4 = new Student("liulu", 23); //添加集合元素 list.add(s1); list.add(s2); list.add(s3); list.add(s4); //排序 Collections.sort(list , new Comparator<Student>(){ //使用比较器 @Override public int compare(Student s1, Student s2) { //让年龄升序排列 int sum = s1.getAge()-s2.getAge(); //年龄相同则按照姓名首字母排序 int num = sum == 0 ? s1.getName().compareTo(s2.getName()): sum; return num; } }); //遍历 for (Student s : list ){ System.out.println("姓名:" + s.getName() + "\t" + "年龄:" + s.getAge()); } } }
注意在Student中继承Comparable或者在sort中重写比较器compareTo()
3. 案例:模拟斗地主
需求:通过程序实现斗地主过程中的洗牌,发牌和看牌
示例代码
package com.collection.collections; import java.util.ArrayList; import java.util.Collections; public class PokerDemo { public static void main(String[] args) { //创建一个牌盒 ArrayList<String> pokers = new ArrayList<>(); /* 往盒子里装牌 方片2 - A 黑桃2 - A 红桃2 - A 梅花2 - A */ //定义花色数组 String[] color = {"♦","♣","♥","♠"}; //定义点数数组 String[] num = {"2","3","4","5","6","7","8","9","10","J","Q","K","A"}; //拼接 for (String s1 : color){ for (String s2 : num){ pokers.add(s1+s2); } } pokers.add("小王"); pokers.add("大王"); //洗牌 Collections.shuffle(pokers); //创建玩家牌库 ArrayList<String> zsPokers = new ArrayList<>();//张三 ArrayList<String> lsPokers = new ArrayList<>();//李四 ArrayList<String> wmzPokers = new ArrayList<>();//王麻子 ArrayList<String> dpPokers = new ArrayList<String>();//底牌 //发牌 for (int i = 0; i < pokers.size(); i++) { String poker = pokers.get(i); if (pokers.size() - i <= 3){ dpPokers.add(poker); } else if (i % 3 == 0){ zsPokers.add(poker); } else if (i % 3 == 1){ lsPokers.add(poker); } else if (i % 3 == 2){ wmzPokers.add(poker); } } //看牌 System.out.println("牌库:" + pokers); look("张三",zsPokers); look("李四",lsPokers); look("王麻子",wmzPokers); System.out.println("底牌是:" + dpPokers); } //看牌 public static void look(String name , ArrayList<String> list){ System.out.println(name + "的手牌是:"); for (String poker : list){ System.out.print(poker + " "); } System.out.println(); } }
4. 案例:模拟斗地主升级版
需求:通过程序实现斗地主过程中的洗牌发牌和看牌,要求:对牌进行排序
使用了HashMap存牌库,用ArrayList存索引,用TreeSet存手牌
package com.collection.collections; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.TreeSet; public class PokerExDemo { public static void main(String[] args) { //定义一个HashMap集合对象用作牌库 HashMap<Integer, String> map = new HashMap<>(); //定义一个ArrayList集合对象存储索引 ArrayList<Integer> keys = new ArrayList<>(); //定义TreeSet用于存储玩家手牌 TreeSet<Integer> zsPokers = new TreeSet<>(); TreeSet<Integer> lsPokers = new TreeSet<>(); TreeSet<Integer> wmzPokers = new TreeSet<>(); TreeSet<Integer> dpPokers = new TreeSet<>(); //定义花色数组 String[] color = {"♦","♣","♥","♠"}; //定义点数数组 String[] num = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"}; //拼接 Integer i = 0; for (String s1 : num){ for (String s2 : color){ map.put(i,s2 + s1); keys.add(i); i ++; } } //小王大王 map.put(52,"小王"); map.put(53,"大王"); keys.add(52); keys.add(53); //洗牌 : 洗索引 Collections.shuffle(keys); //抽牌 for (int j = 0; j < keys.size(); j++) { Integer poker = keys.get(j); if (keys.size() - j <= 3){ dpPokers.add(poker); } else if (j % 3 == 0){ zsPokers.add(poker); } else if (j % 3 == 1){ lsPokers.add(poker); } else if (j % 3 == 2){ wmzPokers.add(poker); } } //看牌 look("张三", zsPokers , map ); look("李四", lsPokers , map ); look("王麻子", wmzPokers , map ); look("底牌", dpPokers , map ); // System.out.println(map); // System.out.println(keys); } //看牌方法 public static void look(String name , TreeSet<Integer> set, HashMap<Integer,String> map){ System.out.println(name + "的牌是:"); for (Integer i : set){ System.out.print(map.get(i) + " "); } System.out.println(); } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· winform 绘制太阳,地球,月球 运作规律
· 上周热点回顾(3.3-3.9)