文章目录
前言
我们在学习完数组后,就需要更加深入的学习储存更多的集合了,在这里我们会学习集合是什么,由什么组成,该如何去使用
一、集合
1.什么是集合
集合是有别于数组,但又包含数组的能对多个对象进行操作的对象容器,可以实现数组的操作功能。
2.集合和数组的区别
数组的长度是固定的,而集合的长度是不固定的
数组能够存储基本数据类型和引用数据类型,而集合只能够存储引用数据类型
当然如果想要传入基本数据类型到集合中只需要把基本数据类型装包成引用类型即可
二、Collection
1.Colloction体系
Colloction本身是一个接口,而其下又有两个接口,一个是List接口一个是Set接口,其中List接口又包含两个类,一个ArrayList类和LinkList类,Set接口则包含HashSet类和SortedSet接口,而SortedSet又由TreeSet类实现,其如下图
图例2.Colloction的使用
0)Cat类
我重写了toString方法和equals方法
代码示例import java.io.Serializable;
public class Cat implements Serializable {
private String catName;
private Integer catAge;
public Cat(String catName, Integer catAge) {
this.catName = catName;
this.catAge = catAge;
}
public String getCatName() {
return catName;
}
public void setCatName(String catName) {
this.catName = catName;
}
public Integer getCatAge() {
return catAge;
}
public void setCatAge(Integer catAge) {
this.catAge = catAge;
}
@Override
public String toString(){
return "猫名字是:"+this.catName+"\t"
+"猫年龄是:"+this.catAge;
}
@Override
public boolean equals(Object obj){
//1、判断两个类是否相同
if(this.getClass() == obj.getClass()){
return true;
}
//2、判断obj是否为空
if (obj == null){
return false;
}
//3、判断引用指向的实际类型是否相同
if(obj instanceof Cat){
//4、类型强制转换
Cat cat = (Cat)obj;
//5、逐个比较属性值是否相同
if(this.getCatName().equals(cat.getCatName()) || this.getCatAge().equals(cat.getCatAge())){
return true;
}
}
return false;
}
}
1)Colloction的基本使用方法
基本使用方法包括但不限于,向集合中添加元素,删除集合中的元素,遍历集合中的元素,判断集合
代码示例public class Test2 {
public static void main(String[] args) throws NullPointerException {
Collection collection = new ArrayList();
//向集合中添加元素
collection.add("苹果");
collection.add("西瓜");
collection.add("樱桃");
//==================集合基本操作============
//判断是否包含某元素
System.out.println(collection.contains("西瓜"));
System.out.println(collection.contains("榴莲"));
//判断集合的大小、是否为空
System.out.println(collection.size());
collection.remove("西瓜");
System.out.println(collection.size());
System.out.println(collection.isEmpty());
//==================遍历集合================
//使用for:each遍历
for (Object o : collection) {
System.out.println(o);
}
//使用迭代器
Iterator iterator = collection.iterator();
if(iterator.hasNext()){
String next = (String)iterator.next();
System.out.println(next);
}
}
}
2)Colloction对对象使用方法
和自己添加创建数据的时候是一样的,只不过就是在最前面添加了创建所需对象的步骤,其他的步骤与基础的方法近乎一模一样,同样是向集合中添加元素,删除集合中的元素,遍历集合中的元素,判断集合
代码示例public class Test2 {
public static void main(String[] args) throws NullPointerException {
Cat cat = new Cat("小周",34);
Cat cat1 = new Cat("老周",32);
Cat cat2 = new Cat("中州",34);
Collection collection = new ArrayList();
//向集合中添加元素
collection.add(cat);
collection.add(cat1);
collection.add(cat2);
//==================集合基本操作============
//判断是否包含某元素
System.out.println(collection.contains(cat1));
System.out.println(collection.contains("asd"));
//判断集合的大小、是否为空
System.out.println("集合大小"+collection.size());
collection.remove(cat);
System.out.println("删除一个元素后集合大小"+collection.size());
System.out.println("清空前集合是否为空"+collection.isEmpty());
//==================遍历集合================
//使用for:each遍历
for (Object o : collection) {
System.out.println(o);
}
//使用迭代器
Iterator iterator = collection.iterator();
while(iterator.hasNext()){
Cat next = (Cat)iterator.next();
System.out.println(next);
}
collection.clear();
System.out.println("清空后集合是否为空"+collection.isEmpty());
System.out.println("集合大小"+collection.size());
}
}
3.List集合
1)List的基本使用方法
因为list本身就包含了Collection的方法,所以Collocetion所拥有的方法,List也有而List区别于Collection的就是自身有一个lisrIterator迭代器
代码示例public class Test2 {
public static void main(String[] args) throws NullPointerException {
Cat cat = new Cat("小周",34);
Cat cat1 = new Cat("老周",32);
Cat cat2 = new Cat("中州",34);
List list = new ArrayList();
//向集合中添加元素
list.add(cat);
list.add(cat1);
list.add(cat2);
//==================集合基本操作============
//判断是否包含某元素
System.out.println(list.contains(cat1));
System.out.println(list.contains("asd"));
//判断集合的大小、是否为空
System.out.println("集合大小"+list.size());
/*list.remove(cat);
System.out.println("删除一个元素后集合大小"+list.size());
System.out.println("清空前集合是否为空"+list.isEmpty());*/
//==================遍历集合================
//使用for:each遍历
for (Object o : list) {
System.out.println(o);
}
//使用迭代器
Iterator iterator = list.iterator();
if(iterator.hasNext()){
Cat next = (Cat)iterator.next();
System.out.println(next);
}
//使用listIterator迭代器
//================从前往后遍历================
ListIterator listIterator = list.listIterator();
while(listIterator.hasNext()){
Cat next = (Cat)listIterator.next();
System.out.println("从前往后遍历"+listIterator.nextIndex()+":"+next);
}
//================从后往前遍历================
while(listIterator.hasPrevious()){
Cat previous = (Cat)listIterator.previous();
System.out.println("从后往前遍历"+listIterator.previousIndex()+":"+previous);
}
//清空集合
list.clear();
System.out.println("清空后集合是否为空"+list.isEmpty());
System.out.println("集合大小"+list.size());
}
}
结果:
true
false
集合大小3
猫名字是:小周 猫年龄是:34
猫名字是:老周 猫年龄是:32
猫名字是:中州 猫年龄是:34
猫名字是:小周 猫年龄是:34
1:猫名字是:小周 猫年龄是:34
2:猫名字是:老周 猫年龄是:32
3:猫名字是:中州 猫年龄是:34
3:猫名字是:中州 猫年龄是:34
2:猫名字是:老周 猫年龄是:32
1:猫名字是:小周 猫年龄是:34
清空后集合是否为空true
集合大小0
其中我们可以看到使用了listIterator后既可以从前往后也可以从后往前
2)List存储数字后装箱
当我们在创建一个List集合后,如果我们往里面添加数据的时候是直接输入的数字,那想删除的时候就不能直接输入需要删除的数字,不然会报数组下标越界的错误
代码示例public class Test2 {
public static void main(String[] args) throws NullPointerException {
List li = new ArrayList<>();
li.add(20);
li.add(30);
li.add(40);
li.add(50);
li.add(60);
li.remove(60);
}
}
结果:
Exception in thread "main" java.lang.IndexOutOfBoundsException: Index 30 out of bounds for length 5
导致报错的原因是因为集合与数组的区别,数组能接收基本数据类型和引用数据类型,而集合只能接收引用数据类型,所以当你使用remove 的时候本质是输入的是需要删除的下标,所以此时只需要把基本数据类型改成引用类型即可
代码示例public class Test2 {
public static void main(String[] args) throws NullPointerException {
List li = new ArrayList<>();
li.add(20);
li.add(30);
li.add(40);
li.add(50);
li.add(60);
System.out.println("未删除前"+li.toString());
//把基本数据类型的60转换成引用数据类型的60,并删除60这个元素
li.remove(Integer.valueOf(60));
System.out.println("删除后集合大小:"+li.size()+"\t"+"集合元素"+li.toString());
}
}
结果:
未删除前[20, 30, 40, 50, 60]
删除后集合大小:4 集合元素[20, 30, 40, 50]
4.ArrayList
0)ArrayList构成
其是一个有下标的数组,实现了List接口,且长度不固定,但是因为其数组的性质,所以在增删方面较慢,在查找方面较快
1)ArrayList的基本使用方法
本身为List接口的一个实现类,所以在List中有的功能在ArrayList都能实现
代码示例public class Test2 {
public static void main(String[] args) throws NullPointerException {
Cat cat = new Cat("啊啊",12);
Cat cat1 = new Cat("啊aa",145);
Cat cat2 = new Cat("啊bb",241);
//==============1、添加元素=====================
ArrayList arrayList = new ArrayList<>();
arrayList.add(cat);
arrayList.add(cat1);
arrayList.add(cat2);
System.out.println("未删除前"+arrayList.toString());
//==============2、删除元素=====================
//new出一个新的Cat后删除集合中与之相同的元素
arrayList.remove(new Cat("啊aa",145));
System.out.println("删除后集合大小:"+arrayList.size()+"\t"+"集合元素"+arrayList.toString());
//==============3、遍历元素=====================
//使用迭代器
Iterator iterator = arrayList.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
//使用listIterator迭代器
//顺序
ListIterator listIterator = arrayList.listIterator();
while (listIterator.hasNext()){
System.out.println(listIterator.nextIndex()+":"+listIterator.next());
}
System.out.println(" ");
//逆序
while (listIterator.hasPrevious()){
System.out.println(listIterator.previousIndex()+":"+listIterator.previous());
}
//==============4、查找=====================
Cat o = (Cat)arrayList.get(1);
System.out.println(o.toString());
arrayList.clear();
}
}
2)ArrayList的斗地主案例
public class Test2{
public static void main(String[] args) {
/**
* 1.准备牌
*/
//存储四种花色
List<Object> flowerList = new ArrayList<>();
flowerList.add("♥");
flowerList.add("♣");
flowerList.add("♠");
flowerList.add("♦");
/*测试打印出花色集合
for (Object o : flowerList) {
System.out.println("o = " + o);
}*/
//存储13个序列
List<Object> orderList = new ArrayList<>();
orderList.add("2");
orderList.add("a");
orderList.add("k");
orderList.add("q");
orderList.add("j");
for (int i = 3; i <=10 ; i++) {
orderList.add(i);
}
/*测试打印出orderList的元素
Iterator<Object> iterator = orderList.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}*/
//创建总集合存储所有花色
List<Object> allList = new ArrayList<>();
for (Object o : flowerList) {
for (Object o1 : orderList) {
allList.add(o+""+o1);
}
}
//加入大王小王
allList.add("大王");
allList.add("小王");
//测试打印出所有集合
for (Object o : allList) {
System.out.print(o+" ");
}
System.out.println();
System.out.println("===============");
/**
* 2.洗牌
*/
//开始洗牌
Collections.shuffle(allList);
//测试打印出已经被打乱的所有牌
for (Object o : allList) {
System.out.print(o+" ");
}
System.out.println();
System.out.println("===============");
/**
* 3.发牌
* 要求: 1人17张牌,剩余3张作为底牌,一人一张轮流发牌:集合的索引(0-53)%3
* 定义4个集合,存储3个玩家的牌和底牌
* 素引%2,有两个值(0,1) 0%2=0 1%2=1 2%2=0 3%2=1
* 索引9%3,有三个值(0,1,2) 0%3=0 1%3=1 2%3=2 3%3=0
* 索引>=51改底牌发牌
*/
//创建三个人的集合
List<Object> player1 = new ArrayList<>();
List<Object> player2 = new ArrayList<>();
List<Object> player3 = new ArrayList<>();
//创建底牌集合
List<Object> lastCard = new ArrayList<>();
//开始发牌
for(int i = 0;i < allList.size();i++){
// 获取牌面
String card = (String)allList.get(i);
// 分别按照索引存储分配牌
if(i>=51){
lastCard.add(card);
}
if(i%3==0){
player1.add(card);
}
if(i%3==1){
player2.add(card);
}
if(i%3==2){
player3.add(card);
}
}
//遍历玩家
for (Object o : player1) {
System.out.print("玩家1:"+o+" ");
}
System.out.println();
System.out.println("===============");
for (Object o : player2) {
System.out.print("玩家2:"+o+" ");
}
System.out.println();
System.out.println("===============");
for (Object o : player3) {
System.out.print("玩家3:"+o+" ");
}
System.out.println();
System.out.println("===============");
//遍历底牌
for (Object o : lastCard) {
System.out.print("底牌:"+o+" ");
}
}
}
5.LinkList
1)LinkList构成
与ArrayList一样,实现是List接口,只不过区别于ArrayList的是这个是由双链表构成的,所以相比之下在查找方面会较慢,但是在增删方面会较快
2)LinkedList的基本使用方法
同样是创建一个LinkedList对象,然后进行与ArrayList无二异的添加,删除,查询,判断操作
代码示例public class Test2 {
public static void main(String[] args) throws NullPointerException {
Cat cat = new Cat("啊啊",12);
Cat cat1 = new Cat("啊aa",145);
Cat cat2 = new Cat("啊bb",241);
//==============1、添加元素=====================
LinkedList linkedList = new LinkedList<>();
linkedList.add(cat);
linkedList.add(cat1);
linkedList.add(cat2);
System.out.println("未删除前"+linkedList.toString());
//==============2、删除元素=====================
//new出一个新的Cat后删除集合中与之相同的元素
linkedList.remove(new Cat("啊aa",145));
System.out.println("删除后集合大小:"+linkedList.size()+"\t"+"集合元素"+linkedList.toString());
//==============3、遍历元素=====================
//使用迭代器
Iterator iterator = linkedList.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
//使用listIterator迭代器
//顺序
ListIterator listIterator = linkedList.listIterator();
while (listIterator.hasNext()){
System.out.println(listIterator.nextIndex()+":"+listIterator.next());
}
System.out.println(" ");
//逆序
while (listIterator.hasPrevious()){
System.out.println(listIterator.previousIndex()+":"+listIterator.previous());
}
//==============4、查找=====================
Cat o = (Cat)linkedList.get(1);
System.out.println(o.toString());
linkedList.clear();
}
}
6、泛型
1)什么是泛型
我们都知道在创建一个方法的时候,我们会给定这个方法所需要的参数类型,而方法的那个参数类型是固定的,但是泛型却是不固定的,所以使用泛型的好处就是,当你需要使用什么类型的时候就可以是什么类型,当然这个类型只能是引用类型,不能世纪初类型
2)泛型类
当我们创建一个类的时候可以给他传递一个泛型,而这个泛型可以用在类中所创建的方法中,并去使用
代码示例public class Test2 {
public static void main(String[] args) throws NullPointerException {
Good<String> st = new Good<String>();
st.say("hello");
Good<Integer> objectGood = new Good<Integer>();
objectGood.say(114514);
}
}
class Good <T>{
public void say(T t){
System.out.println(t);
}
}
比如我这里创建了一个泛型的类Good,然后在里面创建了一个say方法并使用这个泛型,而在main方法里面创建这个实际对象的时候我就给它赋了确切的类型,这样Good类的泛型就变成我给定的引用类型,虽然这样看类似于重写方法,但是又异于重写
3)泛型接口
我们创建一个接口时,可以在接口名的后面添加泛型,这样在我们实现这个接口的时候,就可以指定自己需要的类型
代码示例public interface UserDao<T> {
List<T> queryAllAdmin();
}
当我们创建了他的实现类时候,就可以给定我们程序所需要传递的类
代码示例public class UserDaoImpl implements UserDao<Cat> {
@Override
public List<Cat> queryAllAdmin() {
return null;
}
}
这里我传递了一个Cat类,那么这个List集合就只能添加Cat类型的数据了
4)泛型方法
泛型方法的创建与泛型类的创建相似,是在方法名前添加< T > T
代码示例public class Test2 {
public static void main(String[] args) throws NullPointerException {
show("hello");
show(1452);
show(3.1415926);
}
public static <T> T show(T t){
System.out.println("泛型方法"+t);
return t;
}
}
输出:
泛型方法hello
泛型方法1452
泛型方法3.1415926
5)泛型集合
之前我们使用集合的时候,我们在集合后未使用泛型,这样我们的集合里面任何数据都能添加
代码示例public class Test2 {
public static void main(String[] args) throws NullPointerException {
ArrayList objects = new ArrayList<>();
objects.add("苹果");
objects.add("香蕉");
objects.add(123);
Iterator iterator = objects.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
但是我们为了集合元素的统一性,所以主动添加泛型
public class Test2 {
public static void main(String[] args) throws NullPointerException {
ArrayList<String> objects = new ArrayList<>();
objects.add("苹果");
objects.add("香蕉");
objects.add(123);//在编译器里面这一行会报错
Iterator iterator = objects.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
当我们往集合里面添加对象的时候也可以指定所需要的对象,然后在使用增强for进行遍历的时候就不需要进行类型转换了
代码示例public class Test2 {
public static void main(String[] args) throws NullPointerException {
Cat cat = new Cat("啊啊",12);
Cat cat1 = new Cat("啊aa",145);
Cat cat2 = new Cat("啊bb",241);
ArrayList<Cat> cats = new ArrayList<>();
cats.add(cat);
cats.add(cat1);
cats.add(cat2);
for (Cat object : cats) {
System.out.println(object);
}
}
}
结果:
[猫名字是:啊啊 猫年龄是:12]
[猫名字是:啊aa 猫年龄是:145]
[猫名字是:啊bb 猫年龄是:241]
7.Set集合
1)概述
与List一样同样继承了Collection接口,所以能够使用的方法与List的相同,但是与List不相同的是其是无序的,元素不能重复。
因为set是一个接口,所以要使用只能创建它的实现类,HashSet和TreeSet
2)Set的使用
与List的使用方法相同,但是因为是无序且没有下标所以不能像List中从后往前遍历
代码示例public class Test2 {
public static void main(String[] args) throws NullPointerException {
Cat cat = new Cat("小周",34);
Cat cat1 = new Cat("老周",32);
Cat cat2 = new Cat("中州",34);
Set<Cat> set = new HashSet<>();
//向集合中添加元素
set.add(cat);
set.add(cat1);
set.add(cat2);
//==================集合基本操作============
//判断是否包含某元素
System.out.println(set.contains(cat1));
System.out.println(set.contains("asd"));
//判断集合的大小、是否为空
System.out.println("集合大小"+set.size());
/*list.remove(cat);
System.out.println("删除一个元素后集合大小"+list.size());
System.out.println("清空前集合是否为空"+list.isEmpty());*/
//==================遍历集合================
//使用for:each遍历
for (Object o : set) {
System.out.println(o);
}
//使用迭代器
Iterator iterator = set.iterator();
if(iterator.hasNext()){
Cat next = (Cat)iterator.next();
System.out.println(next);
}
//清空集合
set.clear();
System.out.println("清空后集合是否为空"+set.isEmpty());
System.out.println("集合大小"+set.size());
}
}
3)HashSet
本身为Set接口的一个实现类,所以在Set中有的功能在HashSet都能实现
代码示例public class Test2 {
public static void main(String[] args) throws NullPointerException {
Cat cat = new Cat("小周",34);
Cat cat1 = new Cat("老周",32);
Cat cat2 = new Cat("中州",34);
HashSet<Cat> set = new HashSet<>();
//向集合中添加元素
set.add(cat);
set.add(cat1);
set.add(cat2);
//==================集合基本操作============
//判断是否包含某元素
System.out.println(set.contains(cat1));
System.out.println(set.contains("asd"));
//判断集合的大小、是否为空
System.out.println("集合大小"+set.size());
/*list.remove(cat);
System.out.println("删除一个元素后集合大小"+list.size());
System.out.println("清空前集合是否为空"+list.isEmpty());*/
//==================遍历集合================
//使用for:each遍历
for (Object o : set) {
System.out.println(o);
}
//使用迭代器
Iterator<Cat> iterator = set.iterator();
if(iterator.hasNext()){
Cat next = iterator.next();
System.out.println(next);
}
//清空集合
set.clear();
System.out.println("清空后集合是否为空"+set.isEmpty());
System.out.println("集合大小"+set.size());
}
}
4)HashSet重写HashCode和equals
当我们在往HashSet集合中添加元素的时候,我们可能会new出一个与之前创建对象时一样的对象,那么这时候能不能放入到集合中呢,答案是可以的,因为我们创建一个新对象后地址发生了改变,从而HashCode值也不相同,所以判断为两个不同的元素所以可以放进集合当中
代码示例public class Test2 {
public static void main(String[] args) throws NullPointerException {
Cat cat = new Cat("小周",34);
Cat cat1 = new Cat("老周",32);
Cat cat2 = new Cat("中州",34);
HashSet<Cat> set = new HashSet<>();
//向集合中添加元素
set.add(cat);
set.add(cat1);
set.add(cat2);
set.add(new Cat("中州",34));
System.out.println("集合大小:"+set.size());
//使用迭代器
Iterator<Cat> iterator = set.iterator();
while(iterator.hasNext()){
Cat next = iterator.next();
System.out.println(next);
}
//清空集合
set.clear();
System.out.println("清空后集合是否为空"+set.isEmpty());
System.out.println("集合大小"+set.size());
}
}
当然我们可以看出这两个是相同的,但是编译器不能,所以这时候我们就需要重写HashCode和equals,当然如果只重写HashCode的话,结果还是会放进集合,所以在使用HashSet集合的时候,就必须两个一起重写
代码示例@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Cat cat = (Cat) o;
return Objects.equals(catName, cat.catName) &&
Objects.equals(catAge, cat.catAge);
}
@Override
public int hashCode() {
return Objects.hash(catName, catAge);
}
所以当我们在创建一个对象的时候,就会根据名字和年龄得出得数据进行比对,所以上面代码的new Cat("中州",34)与之前的相同,所以是一个对象,就不会再被添加进集合中
5)TreeSet
是基于红黑树实现的存储方式,同样有着Set的使用方法,当然单纯的使用这个集合会导致编译器报class Cat cannot be cast to class java.lang.Comparable这个错误,所以此时我们需要在实体类中实现Comparable接口,并重写compareTo方法,除此之外的API的使用方法与之前的集合几乎一模一样
代码示例@Override
public int compareTo(Cat cat) {
//通过String比较,得到一个值,如果这个值为0则比较年龄
int n1 = this.getCatName().compareTo(cat.getCatName());
int n2 = this.getCatAge()-cat.getCatAge();
return n1!=0?n1:n2;
}
三、Map
1.Map体系
通过图片我们可以了解到Map父接口,而后又分了HashMap实现类和SortedMap接口以及它的实现类TreeMap
2.Map
1)Map接口的特点
1、能存储键值对
2、无序,无下标,键唯一,不允许重复
3、值不唯一,允许重复
2)Map接口的应用
与之前的Collection集合的API使用并没有太大差别,只是因为多了键值对所以,多了一些获取键值对的方法例如get()方法通过输入键来获取值,然后就是遍历的时候需要使用keySet和entrySet方法先来获取一个Set集合然后再进行遍历
代码示例public class Test2 {
public static void main(String[] args) throws NullPointerException {
HashMap<String, String> hm = new HashMap<>();
//1、往集合中添加元素
hm.put("001","芳乃");
hm.put("002","日日姬");
hm.put("003","雪风");
hm.put("003","丛雨");
//2、遍历集合
//1)使用keySet遍历
Set<String> keySet = hm.keySet();
for (String key : keySet) {
System.out.println("keySet"+key+hm.get(key));
}
//2)使用entrySet遍历
Set<Map.Entry<String, String>> entries = hm.entrySet();
for (Map.Entry<String, String> entry : entries) {
System.out.println("entrySet"+"键:"+entry.getKey()+"值:"+entry.getValue());
}
//3、删除集合中的元素
hm.remove("003");
System.out.println("删除后 集合大小"+hm.size());
//4、判断
System.out.println(hm.containsValue("丛雨"));
System.out.println(hm.containsKey("001"));
//5、清空集合
hm.clear();
System.out.println("清空完成,此时集合中的元素个数"+hm.size());
}
}
结果:
keySet001芳乃
keySet002日日姬
keySet003丛雨
entrySet键:001值:芳乃
entrySet键:002值:日日姬
entrySet键:003值:丛雨
删除后 集合大小2
false
true
清空完成,此时集合中的元素个数0
3.HashMap
1)HashMap存储结构
是由数组+链表+红黑树组成的
2)HashMap接口的应用
因为是Map接口的实现类所以能够使用Map中的API
代码示例public class Test2 {
public static void main(String[] args) throws NullPointerException {
HashMap<Cat, String> hm = new HashMap<>();
//1、往集合中添加元素
hm.put(new Cat("芳乃",18),"千恋万花");
hm.put(new Cat("日日姬",17),"爱上火车");
hm.put(new Cat("雪风",83),"碧蓝航线");
hm.put(new Cat("丛雨",16),"千恋万花");
//2、遍历集合
//1)使用keySet遍历
Set<Cat> keySet = hm.keySet();
for (Cat key : keySet) {
System.out.println("keySet"+key+hm.get(key));
}
//2)使用entrySet遍历
Set<Map.Entry<Cat, String>> entries = hm.entrySet();
for (Map.Entry<Cat, String> entry : entries) {
System.out.println("entrySet"+"键:"+entry.getKey()+"值:"+entry.getValue());
}
//3、删除集合中的元素
hm.remove(new Cat("雪风",83));
System.out.println("删除后 集合大小"+hm.size());
//4、判断
System.out.println(hm.containsValue("千恋万花"));
System.out.println(hm.containsKey(new Cat("丛雨",16)));
//5、清空集合
hm.clear();
System.out.println("清空完成,此时集合中的元素个数"+hm.size());
}
}
添加进集合的时候使用的是匿名创建,所以在删除和查看是否包含的时候使用的是创建对象的方式,且在Cat类中重写了hashCod方法和equals方法
代码示例@Override
public boolean equals(Object obj){
//1、判断两个类是否相同
if(this.getClass() == obj.getClass()){
return true;
}
//2、判断obj是否为空
if (obj == null){
return false;
}
//3、判断引用指向的实际类型是否相同
if(obj instanceof Cat){
//4、类型强制转换
Cat cat = (Cat)obj;
//5、逐个比较属性值是否相同
if(this.getCatName().equals(cat.getCatName()) || this.getCatAge().equals(cat.getCatAge())){
return true;
}
}
return false;
}
@Override
public int hashCode() {
return Objects.hash(catName, catAge);
}
4.TreeMap
1)HashMap存储结构
是由红黑树组成的
2)HashMap接口的应用
是基于红黑树实现的存储方式,单纯的使用这个集合会导致编译器报class Cat cannot be cast to class java.lang.Comparable这个错误,所以此时我们需要在实体类中实现Comparable接口,当然如果不想在实体类中实现这个接口也可以直接在方法中用匿名内部类的方式去创建Comparable对象在这里面去写排序规则
代码示例@Override
public int compareTo(Cat cat) {
//通过String比较,得到一个值,如果这个值为0则比较年龄
int n1 = this.getCatName().compareTo(cat.getCatName());
int n2 = this.getCatAge()-cat.getCatAge();
return n1!=0?n1:n2;
}
这里重写了compareTo方法后使用HashMap的代码得到的结果就会按照年龄大小进行排序
keySet[猫名字是:丛雨 猫年龄是:16]千恋万花
keySet[猫名字是:日日姬 猫年龄是:17]爱上火车
keySet[猫名字是:芳乃 猫年龄是:18]千恋万花
keySet[猫名字是:雪风 猫年龄是:83]碧蓝航线
entrySet键:[猫名字是:丛雨 猫年龄是:16]值:千恋万花
entrySet键:[猫名字是:日日姬 猫年龄是:17]值:爱上火车
entrySet键:[猫名字是:芳乃 猫年龄是:18]值:千恋万花
entrySet键:[猫名字是:雪风 猫年龄是:83]值:碧蓝航线
删除后 集合大小3
true
true
清空完成,此时集合中的元素个数0
3)LinkedHashMap
是hashmap的子类,而这个子类相较于父类来说,底层是用哈希表+链表实现的,这样保证了有可预测的迭代次序。而且相较于他的父类,LinkedHashMap是一个有序的集合,存储和取出元素的顺序是一样的
示例代码HashMap<Cat, String> hm = new LinkedHashMap<>();
只需要将创建hashmap的代码改成LinkedHashMap的即可
总结
集合也复习完了,还记得上学的时候这一块还是在疫情上网课的时候学的,当时根本没有重视,所以到后面自学框架的时候碰到集合完全就是蒙的,根本不会使用,然后就只能问室友,现在的话虽然以及能够使用集合了,但是时间已经回不去了,真的怀念那段时间。