(集合)java中的哈希表,HashSet,TreeSet

 

 

哈希表是一种数据结构,能够快速定位已存储的数据的地址:

 

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
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值