哈希表是一种数据结构,能够快速定位已存储的数据的地址:
1.通过hashCode()计算哈希码,通过该哈希码定位到内存地址。hash码的计算通常基于对象的某些特有属性进行计算;
2.如果地址不同,则直接存入;
3.如果地址相同,则调用该对象的equals()比较内容;如果内容相同,则丢弃,不同,则顺延一个空间,存入。
HashSet HashMap 都是基于hash表的数据结构进行实现的。
HashSet确保对象唯一,通过hashCode()与equals()来完成
hashCode() 计算不同对象的哈希码
equals() 当地址相同时,判断对象是否相同,如果相同,则丢弃,如果不同,就顺延存入。这样便确保了对象的唯一性
public class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
public Person(String name) {
super();
this.name = name;
}
/**
* Person对象的哈希值计算方法
*/
@Override
public int hashCode() {
return name.hashCode()+age*31;
}
/**
* 比较Person对象是否相同的规则
*/
@Override
public boolean equals(Object obj) {
Person p = (Person)obj;
return this.name.equals(p.getName()) && this.age == p.getAge();
}
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 static void main(String[] args) {
Set<Person> set = new HashSet<Person>();
set.add(new Person("zs1",10));
set.add(new Person("zs2",20));
set.add(new Person("zs3",30));
set.add(new Person("zs1",10));//hachCode()结果相同,equals()结果为true,该对象被丢弃
Iterator<Person> iter = set.iterator();
while(iter.hasNext()) {
Person p = iter.next();
System.out.println(p.getName()+"--"+p.getAge());
}
}
TreeSet确保对象唯一,并且按指定规则排序,通过compare()或compareTo()实现
TreeSet中比较器,返回int值,如果为0,表示相同,则不存,确保唯一。
TreeSet的实现,不依赖hashCode()和equals()。
如,String字符串类实现了Comparable接口,复写了compareTo()
public int compareTo(String anotherString) {
int len1 = value.length;
int len2 = anotherString.value.length;
int lim = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int k = 0;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2; //比较字符的自然顺序
}
k++;
}
return len1 - len2;
}
1. 自定义比较器,实现Comparator接口;在存入TreeSet集合的时候指定比较器。
让集合具备比较功能,而且将覆盖元素自身的比较规则!
应用场景:
a.覆盖对象本身具备的比较规则,如String类默认按自然顺序排序,将其覆盖为按长度排序
b.为其它类(非自己创建的类)指定比较规则,将比较功能传入集合中,让集合具备比较功能
public class Person {
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
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;
}
}
import java.util.Comparator;
public class PersonComparator implements Comparator<Person> {
/**
* 姓名不同
* 存入,并按姓名排序
* 姓名相同,比较年龄
* 年龄不同,则首先按姓名,再按年龄排序
* 年龄也相同,则为同一个对象,不存!
*/
@Override
public int compare(Person o1, Person o2) {
//1.按姓名比较
int comp = o1.getName().compareTo(o2.getName());
//2.姓名相同,则继续按年龄比较,如果年龄相同,则表示同一个对象,不存!
return comp==0?(o1.getAge()-o2.getAge()):comp;
}
}
public static void main(String[] args) {
Set<Person> set = new TreeSet<Person>(new PersonComparator());//传入比较器
set.add(new Person("zs1",10));
set.add(new Person("zs2",20));
set.add(new Person("zs2",15));//姓名相同的情况下,则年龄作为次要排序条件
set.add(new Person("zs1",10));//哈希值相同,equals()结果为true,该对象被丢弃
Iterator<Person> iter = set.iterator();
while(iter.hasNext()) {
Person p = iter.next();
System.out.println(p.getName()+"--"+p.getAge());
}
}
结果:
zs1--10
zs2--15
zs2--20
2. 实现Comparable接口
public class Person implements Comparable<Person>{
private String name;
private int age;
public Person() {
super();
}
public Person(String name, int age) {
super();
this.name = name;
this.age = age;
}
/**
* 排序规则:
* 首先按姓名排
* 姓名相同,再按年龄排
* 年龄也相同,则为同一个对象,不存!
*/
@Override
public int compareTo(Person o) {
int temp = this.name.compareTo(o.getName());
return temp==0 ? (this.age-o.getAge()) : temp;
}
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 static void main(String[] args) {
Set<Person> set = new TreeSet<Person>();
set.add(new Person("zs1",10));
set.add(new Person("zs2",20));
set.add(new Person("zs2",15));//姓名相同的情况下,再按年龄排序
set.add(new Person("zs1",10));//哈希值相同,equals()结果为true,该对象被丢弃
Iterator<Person> iter = set.iterator();
while(iter.hasNext()) {
Person p = iter.next();
System.out.println(p.getName()+"--"+p.getAge());
}
}
结果:
zs1--10
zs2--15
zs2--20