什么是集合?
1.简称集,使用存储多个元素的容器
2.集合和数组的区别
- 元素性:
集合:引用类型(存储基本类型时自动装箱)
数组:基本类型、引用类型 - 元素个数
集合:不固定,可以任意扩容
数组:固定,不能改变容量,列如定义一个int类型长度为5的数组只能最多存入5个在多就不行了 - 集合的好处
不受容器大小限制,可以随时添加、删除元素
提供了大量操作元素的方法(判断、获取等)
3.集合简介
- java的集合体系
单例集合(Collection)
List:ArrayList
Set: HashSet - 双列集合(Map:key,value)
Map:HashMap
🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱
一、List集合特点应用
1.List集合的特点
- 特点:可重复、有序(存取顺序相同)
- 应用:List list = new ArrayList();父接口指向子类对象
2.需求
- 往List集合中添加3个动物,然后遍历
2.1、创建动物实体类
package list;
public class Animal {
private String name;
private Integer age;
public Animal() {}
public Animal(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Animal{" + "name='" + name + '\'' + ", age=" + age + '}';
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public Integer getAge() {return age;}
public void setAge(Integer age) {this.age = age;}
}
2.2、动物测试类
package list;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class Text {
public static void main(String[] args) {
//创建集合对象
List list =new ArrayList();
//创建元素对象
Animal animal1 = new Animal("狗",4);
Animal animal2 = new Animal("狗",4);
Animal animal3 = new Animal("猫",6);
Animal animal4 = new Animal("狮子",9);
//将元素添加到对象中
list.add(animal1);
list.add(animal2);
list.add(animal3);
list.add(animal4);
//List常用的一些方法
//获取索引为2的元素
Object obj = list.get(2);
System.out.println("索引为2的元素是:"+obj);
//获取集合元素的个数
System.out.println("集合的长度为:"+list.size());
}
2.2.1、遍历集合
直接打印集合
System.out.println("----------直接打印集合--------------------");
//直接打印集合
System.out.println(list);
普通遍历集合
System.out.println("----------普通遍历集合--------------------");
//普通遍历集合
for (int i = 0; i < list.size(); i++) {
Object obj2 = list.get(i);
System.out.println("索引为"+i+"的元素是"+obj2);
}
增强for循环遍历集合
System.out.println("----------增强for循环遍历集合--------------------");
//增强for循环遍历集合
int i =0;
for (Object obj3:list) {
System.out.println("索引为"+(i++)+"的元素是"+obj3);
}
2.2.2、通过迭代器遍历集合:
1. 为什么需要迭代器?
- 对过程的重复,称为迭代。
- 迭代器是遍历Collection集合的通用方式,可以在对集合- - 遍历的同时进行添加、删除等操作。
2. 迭代器的常用方法
- next():返回迭代的下一个元素对象
- hasNext(O:如果仍有元素可以迭代,则返回true
注意:列表选代器是List体系独有的遍历方式,可以在对集合遍历的同时进行添加、删除等操作。但是必须通过调用列表选代器的方法来实现
通过普通迭代器遍历集合
System.out.println("-----------通过普通迭代器遍历集合------------------");
//通过普通迭代器遍历集合
//使用步骤:
// 1,根据集合对象获取其对象的选代器对象
Iterator it= list.iterator();
// 判断选代器中是否有元素
while (it.hasNext()){//如果迭代器中有元素,就一直迭代
//如果有就获取元素
Object obj4 = it.next();
System.out.println(obj4);
}
通过列表迭代器遍历集合
System.out.println("-----------通过列表迭代器遍历集合------------------");
//列表迭代器使用
//需求:判断集合中如果有字符串“葡萄”,就在其后边添加一个新的字符串“梨子”
List list2 = new ArrayList();
list2.add("苹果");
list2.add("香蕉");
list2.add("葡萄");
//使用步骤:
// 1,根据集合对象获取其对象的选代器对象
ListIterator lit = list2.listIterator();
// 判断选代器中是否有元素
while (lit.hasNext()){//如果迭代器中有元素,就一直迭代
//如果有就获取元素
Object obj4 = lit.next();
if("葡萄".equals(obj4)){
//必须通过调用列表选代器的方法来实现
lit.add("梨子");
}
System.out.println(obj4);
}
//打印新的list2的值
System.out.println(list2);
}
总结:
普通的选代器在遍历集合的同时不能添加或者删除元素,否则会报:并发修改异常
列表选代器在適历集合的同时可以修改集合中的元素(添加,删除等),必须使用列表选代器中的方法.
🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱
二、泛型简介
- 什么是泛型?
即泛指任意类型,又叫参数化类型(ParameterizedType)对具体类型的使用起到辅助作用,类似于方法的参数。
1.集合类泛型的解释
表示该集合中存放指定类型的元素
- 案例演示(给List集合加上泛型String)
List list = new ArrayList<>() - 泛型的好处
类型安全
避免了类型转换
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String[] args) {
//演示泛型
//创建集合对象
//泛型写成<String>只能写String类型数据,写其他类型的报错 ,”list.add(10);”报错
List<String> list = new ArrayList<>();
//创建元素对象
//将元素对象添加到集合对象中
list.add("飞机");
list.add("火车");
list.add("汽车");
//遍历集合
for(String s:list){
System.out.println(s);
};
}
}
总结: 泛型一般只和集合类相结合使用。
泛型是JDK5的新特性,但是从JDK7开始,后边的泛型可以不用写具体的数据类型了(菱形泛型.)new ArrayList《string》(),可以写成new ArrayList<>()
🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱
三、Collections工具类
1.Collections简介
针对集合进行操作的工具类。
2.常用的成员方法
※根据元素的自然顺序,将指定列表按升序排序
sort(List<T>)
※返回集合的最大元素
max(Collection<T>)
※反转List集合元素
reverse(List<T>)
※使用默认的随机源随机置换指定的列表
shuffle(List<T>)
🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱
四、 Set集合的特点和应用
- Set集合的特点特点:不可重复、无序
- 应用:Set set = new HashSet<>0;
4.案例: Set集合的简单使用
向Set集合中添加五个元素,并遍历打印
A. 向集合中添加元素的方法为: add()
B. 遍历集合的方式:选代器
1.创建集合对象:Set set = new HashSet<>();
2.分别创建五个Student对象
3.使用add方法将Student对象添加到集合中
4.使用选代器遍历集合并打印,注意添加顺序和打印顺序是否相同
4.4、创建学生实体类
import java.util.Objects;
public class Student {
private String name;
private Integer age;
public Student() {}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" + "name='" + name + '\'' + ", age=" + age + '}';
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public Integer getAge() {return age;}
public void setAge(Integer age) {this.age = age;}
}
4.5、创建测试类
import java.util.HashSet;
import java.util.Set;
public class Text {
public static void main(String[] args) {
//创建集合对象
Set<Student> set = new HashSet<>();
//创建对象
Student student1 = new Student("张三",12);
Student student2 = new Student("李四",26);
Student student3 = new Student("李四",48);
Student student4 = new Student("王五",35);
Student student5 = new Student("张三",12);
Student student6 = new Student("李四",26);
//将集合对象添加到元素对象中
set.add(student1);
set.add(student2);
set.add(student3);
set.add(student4);
set.add(student5);
set.add(student6);
}
}
直接遍历循环
//直接遍历集合
System.out.println(set);
通过迭代器遍历集合
Iterator it = set.iterator();
//判断迭代器是否有元素
while (it.hasNext()){
//如果有元素,就获取元素
System.out.println(it.next());
}
通过增强for遍历Set集合
for (Student student:set){
System.out.println(student);
}
4.6、set集合一些问题
- 遍历集合为什么Set集合没有"去重"?
1.因为Set集合保证元素的唯一性依赖: equals()和hashCode ()两个方法。
2.你没有在Student类中重写这两个方法,默认调用的是0bject类中的这两个方法。
3.而Object类中的equals()方法默认比较的是地址值是否相 - 解决方案:
在Student实体类中重写equsls()和hashCode()方法.
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Student student = (Student) o;
return Objects.equals(name, student.name) && Objects.equals(age, student.age);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱
五、Map集合的特点和应用
5.1、Map集合的特点特点:
双列集合,元素由键值对(Entry)构成:key – value
key不可以重复,value可以重复
5.2、应用:
Map<T1, T2> map = new HashMap<>();
案例:Map集合的简单使用
需求:向Map集合中添加三个元素,并遍历打印
5.3、分析:
A. 向map集合中添加元素的方法为:put)
B. 遍历集合的方式:获取所有的key: keySet()遍历keySet,通过key获取value: get)
C. 遍历keySet的方法: iterator()
5.4、步骤:
1.创建集合对象:Map<Integer, Student> map = new HashMap<>();
2.分别创建三个Student对象
3.使用put方法将Student对象添加到集合中
4.获取所有的key,并使用选代器遍历
5.通过key分别获取对应的value并打印
5.5、创建学生实体类
import java.util.Objects;
public class Student {
private String name;
private Integer age;
public Student() {}
public Student(String name, Integer age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" + "name='" + name + '\'' + ", 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 Objects.equals(name, student.name) && Objects.equals(age, student.age);
}
@Override
public int hashCode() {
return Objects.hash(name, age);
}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
public Integer getAge() {return age;}
public void setAge(Integer age) {this.age = age;}
5.6、创建测试类
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/*
Map集合的特点特点:
双列集合,元素由键值对(Entry)构成:
key (键) - value (值)
注意:
健(key)不可以重复,值(value)可以重复
应用:
Map<TI, T2) map = new HashMap<>();
解释:
T1:表示键的数据类型
T2:表示值的数据类形
*/
/*
成员方法:
V put (K key, V value): 添加元素(健值对的形式),
元素第一次添加,返回null,
重复添加,会用新值覆盖旧值,并返回旧值.
V get (Object key): 根据键获取其对应的值
Set(K) keySet (): 获取所有键的集合
遍历步骤:
1.获取所有键的集合 keySet()
2.遍历所有的键,获取到每一个键 迭代器,增强for.
3.根据建,获取指定的值. get();
*/
public class Test {
public static void main(String[] args) {
//创建集合对象
//键:学生的编号, 值:具体的学生的对象
Map<Integer,Student> map = new HashMap<>();
//创建元素
Student s1 = new Student("张三",25);
Student s2 = new Student("李四",28);
Student s3 = new Student("张三",25);
//将元素添加到集合中
map.put(1,s1);
map.put(2,s2);
map.put(3,s3);
}
}
5.7、直接打印
//根据建,获取值
Student stu = map.get(3);
System.out.println(stu);
//直接打印集合
System.out.println(map);
5.8、 增强for循环
//增强for循环
//获取到所有的键
Set<Integer> keys1 = map.keySet();
for (Integer key:keys1){
//keys1就是双列集合中的每一个键
System.out.println(map.get(key));
}
5.9、迭代器遍历集合
//遍历集合
// 1.获取所有键的集合 keySet() 具有唯一性
Set<Integer> keys = map.keySet();
// 2.遍历所有的键,获取到每一个键 迭代器,增强for.
// 获取迭代器对象
Iterator<Integer> iterator = keys.iterator();
while (iterator.hasNext()){
Integer key = iterator.next();
System.out.println(map.get(key));
}
🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱🐱
六、终极:用集合模拟斗地主
6.1、模拟斗地主发牌之买牌
6.1.1、案例:模拟斗地主发牌
- 需求:使用一个集合对象存储一副扑克牌,将所有扑克牌的顺序打乱然后分发给用集合表示的三个玩家和底牌,并打印玩家和底牌的集合内容
- 步骤:
1.买一副扑克牌将花色和数字分别进行组合,生成所有的普通牌手动添加“大王”、“小王”
2.洗牌使用Collections工具类的shuffle()方法打乱牌的顺序
3.发牌遍历牌堆,将每一张牌分发到三个玩家集合中留三张作为底牌
4.看牌分别打印每个玩家集合的内容
步骤一:买一副扑克牌
- 分析:
1.创建数字数组:String[] nums =(“3”,“4”,“5”,“6”,“7”,“8”,“9”,“10”,“J”,“Q”,“K”,“A”,“2”);
2.创建花色数组:String[] colors = [“方片”,“梅花”,“红桃”,“黑桃”);
3.将每一个花色分别和数字进行拼接colors[i].concat(nums[j]);
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Text {
public static void main(String[] args) {
//1、买牌
//1.1、定义一个双列集合,键:表示牌的编号,值:表示具体的牌,规则:编号越小,牌越小
Map<Integer,String> pokers = new HashMap<>();
//1.2、定义一个单例集合,用来存储所有的的牌号
List<Integer> list = new ArrayList<>();
//1.3、具体买牌动作
//普通牌,52
String[] colors = {"♠","♥","♣","♦"};
String[] numbers = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
int num = 0;//表示牌的编号
//通过循环嵌套,造 普通牌
for(String number : numbers){//外层循环获取所有的点数
for(String color : colors){ //内循环获取所有的花色
String poker = color + number;
//奖牌的编号,具体的牌放到双列集合中
pokers.put(num,poker);
//奖牌的编号放到单列集合中
list.add(num);
//每添加一张牌,编号要自增1
num++;
//大小王
//添加小王
pokers.put(num,"小王");
list.add(num++);
//添加大王
pokers.put(num,"大王");
list.add(num++);
//打印牌
System.out.println("所有牌:"+pokers);
System.out.println("牌的编号:"+list);
步骤二、三:洗牌和发牌
- 分析:
1.使用Collections工具类的shuffle()方法打乱牌堆集合的顺序
2.分别创建三个玩家集合对象和底牌集合对象
3.遍历牌堆的每一张牌,分别将索引对3取模的值为0,1,2的牌存放到三个玩家集合中,将最后三张存放到底牌集合中
//2.洗牌
Collections.shuffle(list);
System.out.println("洗好牌后,编号为:"+list);
//3、发牌
//3.1、定义四个集合,分别表示3个玩家,底牌.
List<Integer> zhangsan = new ArrayList<>();
List<Integer> lisi = new ArrayList<>();
List<Integer> wangwu = new ArrayList<>();
List<Integer> dipai = new ArrayList<>();
//3.2、具体的发牌动作,将索引和3取模,决定发给谁
for (int i = 0; i < list.size(); i++) {
//获取编号
Integer pokerNum = list.get(i);
if(i >= list.size() - 3){
//底牌
dipai.add(pokerNum);
}else if(i % 3 == 0){
zhangsan.add(pokerNum);
}else if(i % 3 == 1){
lisi.add(pokerNum);
}else if(i % 3 == 2){
wangwu.add(pokerNum);
}
}
//3.3、查看具体的牌
System.out.println("张三:"+printPoker(zhangsan, pokers));
System.out.println("李四:"+printPoker(lisi, pokers));
System.out.println("王五:"+printPoker(wangwu, pokers));
System.out.println("底牌:"+printPoker(dipai, pokers));
}
步骤四、看牌
- 分析:
1.将玩家集合中的牌按自然顺序进行排序Collections.sort(List);
2.打印玩家集合中的牌
3.重复上面的操作打印所有玩家的牌和底牌
/* 4.定义一个方法,用来看牌
方法名:printPoker
参数列表:List<Integer>,Map<Integer,String>
返回值:String
*/
public static String printPoker(List<Integer> nums,Map<Integer,String> pokers){
//1.对牌的编号进行升序排列
Collections.sort(nums);
//2.遍历牌的序号集合,获取到每一个编号
StringBuilder sb = new StringBuilder();
for (Integer num : nums){
//num就是要查找的具体牌的编号
//3.根据编号双列集合中查找该编号对应的具体牌
String poker = pokers.get(num);
//4.将获取到的牌进行拼接
sb.append(poker + " ");
}
//5.将最终拼接结果返回即可
String str = sb.toString();
return str.trim();
}
}