学习笔记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();
}
}