java集合详解
一、set定义
1、Set
是元素无序并且不可以重复的集合,被称为集。
2、hashset
HashSet是Set的一个重要实现类,称为哈希集
HashSet中的元素无序并且不可以重复
HashSet中只允许一个null元素【因为不可重复性】
具有良好的存取和查找性能
二、hashset的增加
1、增加
HashSet cat=new HashSet();
cat.add(c);
先创建好hashset这个类的引用cat,
再通过add()方法将值存储到集合中
2、增加两个内容相同的对象
Cat c=new Cat("朵朵",2,"布偶");
Cat c2=new Cat("朵朵",2,"布偶");
打印一下结果,会发现有两条一模一样的数据。这似乎和hashset的不可重复性违背。
但其实并不是这样,这两条内容的引用地址不同,就会添加到一起。
3、剔除重复性的引用——equals和hashcode()组合
hashcode()
1、是为了减少寻找某数的步骤,提高查找的速度。如arraylist需要依次遍历数,才能找到正确的值。
2、而hashcode通过某种定义好的算法,将集合中的值按照某种方式计算出哈希码,根据哈希码分组,分别存储在若干个存储区域。
3、如果需要查找的内容和某个区域的哈希码相同,那么就在符合的区域中遍历。反之,则跳过这个集合。
equals
【有2种写法,只细讲第一种的代码】
public boolean equals(Object o) {
if (this == o) return true;
if(o.getClass()==Cat.class){
Cat cat=(Cat) o;
return getAge() == cat.getAge() &&
Objects.equals(getName(), cat.getName()) &&
Objects.equals(getSpecies(), cat.getSpecies());
}
return false;
}
1、this是当前类的对象,o是传进来的对象
if (this == o) return true;
即判断传入的类的名字是否相等。比如两个对象都是Cat。
2、第二个if中的判断条件是,如果传进来的对象o所对应的class是否是cat的对象的class
如果相等,那么再进一步比较类中的三个属性,name、age、species的值。
3、如果传入的数据hashcode值不相等,那么就绝对不会重复。【因为hashcode相当于已有的几种类型】
接着就会比较equals的值。如果是TRUE的话,那么就会hashset则不会将该条数据加入集合。如果是FALSE,则会加入。
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Cat)) return false;
Cat cat = (Cat) o;
return getAge() == cat.getAge() &&
Objects.equals(getName(), cat.getName()) &&
Objects.equals(getSpecies(), cat.getSpecies());
}
三、删除
1、删除一条数据
cat.remove(c)
2、删除多条数据
则要先将满足条件的对象装入新的集合中
cat.remove(新的集合cat2);
同时要用到增强型for循环【在第四部分详细介绍】
HashSet <Cat> cat2=new HashSet <Cat> ();
for(Cat c7:cat){
if(c7.getAge()<2){
cat2.add(c7);
}
}
cat.removeAll(cat2);
四、集合优化方式
1、泛型
防止强制类型转换时出错,直接在hashset集合创建的时候,就限制只能添加cat的实例对象。
操作步骤:在类名的后面和接口名的后面加上cat。
HashSet <Cat> cat2=new HashSet <Cat> ();
同理,如果迭代器要限制,也可以在创建时后面加上cat。
Iterator <Cat> it2=cat.iterator();
这样就能省去中的cat的强制转换。
System.out.println(((Cat)(it2.next())).toString());
}
2、迭代器—打印集合内容
【由于set没有get元素的方法,需要借助迭代器打印】
集合在打印的过程中,
Iterator it2=cat.iterator();
while(it2.hasNext()) {
System.out.println(((Cat)(it2.next())).toString());
}
hasNext()是判断集合中是否还有下一个值,如果有,就为TRUE。
it2.next()是取出集合中的下一个值。
注意:
但如果打印的语句是System.out.println(((Cat)(it2.next())),取出的内容是
com.company.Cat@3079e610
这种地址需要在Cat类中增加tostring方法
将地址返回出类属性的字符串
@Override
public String toString() {
return "{" +
"姓名='" + name + '\'' +
", 年龄=" + age +
", 类型='" + species + '\'' +
'}';
}
PS:每次要输出集合内容时,都要重新创建一个迭代器的引用对象。
因为上一个迭代器在前面执行过程中,已经将迭代器中的集合值遍历过一遍了,再次调用输出,很可能会空。
3、增强型for循环
使用增强型for循环删除名叫“”小灰“的”猫的信息
for(Cat c6:cat){
if(c6.getName()=="小灰"){
//或者判断条件写作:"小灰".equals(c6.getName())
System.out.println("找到小灰的信息"+c6.toString());
cat.remove(c6);
}
//下面是错误且多余的语句
else{
System.out.println("没有小灰这只猫");
}
增强型for循环的格式是
类名 对象名:要循环的集合或列表名
1、注意由于set的长度是动态变化的,如果删除了一个值后,再进行遍历,可能会报错。应该在if语句后加上break,满足条件后就结束循环。
2、在增强型for循环中判断时,不要出现ifelse语句,这样有很大可能出现在for循环满足FALSE和满足TRUE的情况。
ps、布尔值flag的运用
1)用于查找某个值是否存在
2)通常初始化为TRUE。
3)根据布尔值的类型,输出对应的提示语句
//寻找小黄的信息
Cat c5=null;
Iterator <Cat> it3=cat.iterator();
boolean flag=true;
while(it3.hasNext()){
c5= it3.next();
if(c5.getName()=="小黄"){
break;
}else{
flag=true;
}
}
if(flag){
System.out.println("找到小黄的信息了!");
System.out.println(c5.toString());
}else{
System.out.println("找不到小黄的信息~");
}
温馨提示💓
如果在运用hashset时遇到问题,可以直接关注并私信我,发送报错问题,我看到后会第一时间回复~