Set是元素无序并且不可以重复的集合,被成为集
HashSet 哈希集,是Set的一个重要实现类
主要方法
- boolean add(E e) 如果当前列表中不存在e, 则将e加入列表
- void clear() 从列表中删除所有元素
- boolean contains(Object j) 判断列表中是否有元素j
- Iterator<E> terator() 得到当前列表的遍历器
- boolean remove(Object j) 如果列表中存在元素j,则将其从列表中删除
- int size() 得到列表中元素的个数
使用中我发现,在set中添加String类型的数据时,如果同时添加两个相同的字符串,那么实际上只能添加一个,因为HashSet不允许添加相同的元素。而添加两个相同的对象的时候却可以添加成功,那应该怎么处理呢?
浅显的说,String重写了Object类的equals方法和hashCode方法。因此,在比较的时候,HashSet调用了String类中重写的equals方法和hashCode方法。因此会按照String类中定义的判断方式来比较对象是否相同。
判断两个对象是否相等的方式
首先两个对象的hashCode是否相等,假如相等的话,那么就认为两个对象相等
假如两个对象的hashCode值不等,那么就通过equals方法来判断两个对象是否相等。默认的equals方法是比较两个对象指向的对象在内存中存储的地址的值是否相等。
如果利用对象里的某个值来判断是否相同,则应该怎么处理呢?
- 首先需要重写hashCode方法.(必须重写hashCode方法!)
- 其次需要重写equals方法。
假如只重写equals方法会出现什么情况呢?
只重写equals方法,那么重写的equals方法是无效的!
原因是添加对象时首先会调用父类Object类中的hashCode方法(本地方法,无法根据散列码得到对象的内存地址,但实际上,hashcode是根据对象的内存地址经哈希算法得来的)。因此两个对象的hashCode的值是不相等的!这样就会认为这是两个不同的元素.
public class Student implements Cloneable {
private int age;
private String name;
public Student(int age, String name) {
this.age = age;
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Student [age=" + age + ", name=" + name + "]";
}
@Override
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
public int hashCode() {
return name.hashCode();
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
Student other = (Student) obj;
return other.name.equals(this.name);
}
}
这样就根据Student里的name字段判断是是否传入的是同一个学生对象。
HashMap和HashSet的区别
- HashMap 实现了 Map 接口而HashSet 实现了 Set 接口
- HashMap 储存键值对而HashSet 仅仅存储对象
- 使用 put() 方法将元素放入 map 中而HashSet使用 add() 方法将元素放入 set 中
- HashMap 中使用键对象来计算 hashcode 值而HashSet 使用成员对象来计算 hashcode 值,对于两个对象来说 hashcode 可能相同,所以 equals() 方法用来判断对象的相等性,如果两个对象不同的话,那么返回 false
- HashMap 比较快,因为是使用唯一的键来获取对象而HashSet 较 HashMap 来说比较慢
网友评论