哈希表是一种数据结构,能够快速定位已存储的数据的地址:
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()); } }结果: