💁💁💁:【集合List的学习总结】
💁💁💁:【集合Map的学习总结】
目录
Set(集)
在这一部分,我开始总结集合的Set方法
Set集的元素可以无序但是不可以重复
- HashSet是Set的一个重要实现类,称为哈希集
- HashSet集的元素可以无序但是不可以重复
- HashSet中是允许存在一个null元素的
- 具有良好的存取和查找性能
同样,让我们查看一下JavaAPI的文档介绍,看看HashSet都有什么方法💁💁点击打开JavaAPI
可以看到,Set有添加元素,清空集合,判断集合是否包含某个特定元素,判断是否为空,迭代器等等等很多方法,其中hashCode()和isEmpty()是Set中比较重要的两个方法
上面的是关于HashSet类的常用发介绍,我们可一看到它同样也包括四个构造方法,类似ArrayList
案例
用HashSet存储多个表示颜色的英文单词,并且输出。单词包括:blue,red,black,yellow,和white。
1.首先在eclipse的com.kilig.set这个包下,创建WordDemo这个类,将英文单词添加到HashSet中
2.获取集合的内容
可以看到,当我们想要使用和list一样的方法get去获得元素的时候,发现在set中是没有这个方法的,而且查看API文档,也没有发现有g类似get的方法,那么怎么办呢?
这个时候我们就可以尝试使用Iterator迭代器方法来获取集的元素。(它有两个方法值得注意)
- Iterator接口可以以统一的方式对各种集合元素进行遍历
- hshNext()方法可以检测集合中是否还由下一个元素,如果返回值为true则表示有,如果返回false,则表示没有
- next()方法返回集合中的下一个元素
让我们看看迭代器的流程:
当第一调用hasNext时,箭头指向的是Kilig() 的前面同时检测下一条是否存在数据,然后调用next() 方法调用Kilig数据;紧接着,hasNext()箭头又指向了Groot的前面,判断下面是否有数据,然后又用next()方法调用得到Groot的数据。当在使用hasNext()在进行判断时,发现下面无数据,跳出循环。
所以我们可以这样:Iterator it =word.iterator(); 通过word调用迭代器的方法Iterator(),然后把结果存放在Iterator这个引用中。
3.插入新元素
可以看到,当我们插入一个重复的数据时,系统是不会判断并且报错的,虽然插入失败,但是不会报错。
案例练习:IT公司人员管理信息
需求:
- 添加和显示人员信息
- 查找某个员工信息并且输出
- 修改人员的调动信息,实现删除员工的信息
分析过程:
- 首先我们需要分析该管理信息内都有什么成员属性需要去添加,名字,年龄,职位名称
- 再看看需要添加什么样的方法,构造方法,获取和设置属性值得方法,其他方法
添加和显示人员信息
1.首先在eclipse中的com.kilig.set的包下创建StaffIT类,并且完善成员属性
package com.kilig.list;
public class StaffIT {
private String name;
private int age;
private String jobName;
}
2.定义构造方法,和get,set方法跟前面list中的类似
3.定义测试类,将人员名单和操作放入测试类,在com.kilig.set下创建StaffTest测试包,进行测试执行。
3.1创建对象,生成人员名单
3.2将对象放入HashSet对象中
3.3显示输出人员信息
为什么会输出显示这样的原因呢?在面向对象中这是地址信息。所以我们需要在StaffIT中重写添加toString方法,回到StaffIT
生成完之后,我们回到StaffTest中,重新运行一下!
3.4添加与Kilig属性一样的人员
疑问:在上面的那个小案例中,我们看到,相同的字符串是不允许添加到集合中的,可是为什么在这儿显示出了两个一样恶=的成员信息呢?
要想进行检查和证明,那么让我们首先在StaffIT中重写toString方法,调用hashCode和equals两个方法。我们可以再eclipse中默认生成这两个方法看看。
补充一个小知识:哈希表
哈希表 的数据结构,可以提高数据的查找速度。比如:
当我们需要存储1-100,100个数据的话,我们如果使用数组(Arry)或者ArrayList来进行存储。此时如果需要查找该集合或者数组中的某个元素时,我们就需要指针去一个一个遍历一遍,进行比对。即使该需要查找的元素不在这个数组或集合内,仍要遍历一遍。
而哈希表则是根据不同规则分成的不同区域,不同数据放在不同的区域内。eclipse自动生成的规则已经足够我们使用了。
比如哈希表按照"n%3"这个规则去区分1-100的数字,按照这个规则将不同的数据存储在不同的区域内,然后这个时候,如果在想要取得某一个数,只要对比该元素时属于哪一个区域部分,然后在该区域内遍历就行了,极大的缩短了遍历的时间和效率。
因此,判断我们所需要找的元素在哪个区域内,用的就是hashCode()方法,而判断哪个元素使我们需要的用的就是equals()方法。
hashCode方法就不需要我们进行改变的,规则是被定好的。那么我们知道hashCode相同不一定是同一个对象,所以我们需要在不同的区域使用equals方法进行比对。所以我们需要重写一下我们的equals方法:
- this是当前对象,obj是我们传进来的对象。如果两个对象相等,那么肯定是同一个对象。
- 如果不相等,那么首先调用 obj.getClass() == StaffIT.class 判断obj对象所对应的Class是不是StaffIT
- 如果是,那么强制转化为StaffIT对象,并且判断两个对象的属性是否相等(name, age, jobName这三个属性)
- 如果这些情况都不满足,那么不相等,返回fause
再次运行一遍,让我们看一看效果:(set集合是不允许添加重复类的)
4.查找Davied的信息,并且输出
我们添加一个新的员工信息Davied。
方法一:一般我们使用Davied的对象名字personnelFour去查找!
方案二:如果我们不知道Davied的这个对象名字personnelFour,我们只知道Davied。因此在这儿我们需要去遍历集合,在集合中取出StaffIT的元素
【注意】需要我们重新导入迭代器,因为在我们代码的最开始之前的部分,调用过一次迭代器,遍历过一次,因此,next迭代到最后已经运行完了,所以在这部分我们需要重新导入一次。
5.删除员工信息:
补充泛型
知识点,去除代码中的黄色警告⚠️部分
为什么?
我们在翻看我们的程序时,发现,代码很多部分都有警告⚠️的黄色部分,让我们看看他们的警示信息
JAVASE5.0 引入了Generic泛型,在没有泛型的时候,我们对类型OBJ的引用来实现任意化,而任意化的缺点就是显示的强制类型转化。
就是我们前面底下做了强制化的处理,转化为我们所需要的类型。然而强制转化的缺点就是必须要求next的类型必须是StaffIT所要求的类型。
测试:
可以看到,当我们强制转化的类型变为String时,此时不是StaffIT所要求的类型,就会发生类型转化异常的报错❌!StaffIT类型不可以转化为String类型
怎么解决?那么此时我们引入泛型,就可以有效解决强制转换的问题。因为泛型要求我们在程序中添加的数据必须是我们所需要的类型。
方法一:
- 手动添加,在我们有黄色警示⚠️的位置手动加入:<要求的类型> 此时就会限制程序我们要求的类型
- 然后在强制转换处,删除强制转换的内容就OK🙆♂️了。
方法二:自动改变
点击确定,直接使用泛型。
此时我们可以看到我们的程序没有一点报错!!
让我们来进行数据的删除:(增强型for循环遍历集合)
删除Kilig的信息并且重新输出:
是用两次增强for循环进行遍历
在此处,我们使用boolean型进行判断是否完全删除成功过删除成功。
下面附上全部的代码片段:
StaffIT.java
package com.kilig.list;
public class StaffIT {
private String name;
private int age;
private String jobName;
// 构造方法
public StaffIT(String name, int age, String jobName) {
super();
this.name = name;
this.age = age;
this.jobName = jobName;
}
// set和get方法
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;
}
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
@Override
public String toString() {
return "StaffIT [name=" + name + ", age=" + age + ", jobName=" + jobName + "]";
}
// hashCode和equal
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((jobName == null) ? 0 : jobName.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
// 相等则返回true,不用继续比较属性
if(this ==obj)
return true;
// 判断obj是否为staffIT类的对象
if(obj.getClass() == StaffIT.class) {
StaffIT staffIT =(StaffIT)obj;
return staffIT.getName().equals(name)&&(staffIT.getAge()==age)&&(staffIT.getJobName().equals(jobName));
}
return false;
}
}
StaffTest.java
package com.kilig.list;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
public class StaffTest {
public static void main(String[] args) {
// TODO Auto-generated method stub
// 定义对象
StaffIT personnelOne =new StaffIT("Kilig", 24, "Java backend engineer");
StaffIT personnelTwo =new StaffIT("Groot", 20, "Network security engineer");
// 将对象放入HashSet对象中
Set<StaffIT> staffList = new HashSet<StaffIT>();
staffList.add(personnelOne);
staffList.add(personnelTwo);
// 显示输出人员信息
System.out.println("===IT 人员管理花名表===");
Iterator<StaffIT> it =staffList.iterator();
while (it.hasNext()) {
System.out.println(it.next()+" ");
}
System.out.println("***************************************************************");
// 添加重复成员Kilig
StaffIT personnelThree =new StaffIT("Kilig", 24, "Java backend engineer");
staffList.add(personnelThree);
System.out.println("===重复IT 人员管理花名表===");
it =staffList.iterator();
while (it.hasNext()) {
System.out.println(it.next()+" ");
}
System.out.println("***************************************************************");
// 添加新成员
StaffIT personnelFour =new StaffIT("Davied", 30, "Web manager");
staffList.add(personnelFour);
System.out.println("===添加新成员后IT 人员管理花名表===");
it =staffList.iterator();
while (it.hasNext()) {
System.out.println(it.next()+" ");
}
// 在集合中查找Davied的信息,并且输出
System.out.println("方案一");
// 方案一:使用对象名字personnelFour
if (staffList.contains(personnelFour)) {
System.out.println("Davied 被找到了 ");
System.out.println(personnelFour);
}else {
System.out.println("Davied 不存在,他不是我们的员工1");
}
System.out.println("方案二");
// 方案二:直接使用名字Davied
boolean flag =false;
StaffIT sName = null;
it =staffList.iterator();
while (it.hasNext()) {
sName =it.next(); //强制转换
if(sName.getName().equals("Davied")) {
flag =true;//找到了
break;
}
}
if(flag) {
System.out.println("Davied 被找到了! ");
System.out.println(sName);
}else {
System.out.println("Davied 没有被找到了!他不是我们的员工 ");
}
// 删除Kilig,并且打印输出
for(StaffIT staffIT:staffList) {
if("Kilig".equals(staffIT.getName())) {
staffList.remove(staffIT);
}
}
System.out.println("***************************************************************");
System.out.println("删除Kilig后的员工信息");
for(StaffIT staffIT:staffList) {
System.out.println(staffIT);
}
// 删除集合中的所有员工信息
System.out.println("***************************************************************");
boolean flag1 =staffList.removeAll(staffList);
if(flag1) {
System.out.println("员工都离职,公司倒闭!");
}else {
System.out.println("员工还在!");
}
}
}