HashSet,LinkedHashSet和TreeSet

先来看看HashSet和LinkedHashSet的一段测试代码:


package set;

import java.util.HashSet;
import java.util.LinkedHashSet;

public class Test1 {
	
	public static void main(String a[]) {

		HashSet<String> set = new HashSet<String>();

		set.add("a5");
		set.add("a6");
		set.add("a7");
		set.add("a3");
		set.add("a4");
		set.add("a");
		set.add("a1");
		set.add("a2");

		System.out.println(set);

		LinkedHashSet<String> linkedHashSet = new LinkedHashSet<String>();

		linkedHashSet.add("a5");
		linkedHashSet.add("a6");
		linkedHashSet.add("a7");
		linkedHashSet.add("a3");
		linkedHashSet.add("a4");
		linkedHashSet.add("a");
		linkedHashSet.add("a1");
		linkedHashSet.add("a2");

		System.out.println(linkedHashSet);

	}
}


打印结果:
[a, a1, a2, a3, a4, a5, a6, a7]
[a5, a6, a7, a3, a4, a, a1, a2]


个人对HashSet的无序性理解:

  1. 前提,对于同一个HashSet来说
  2. 无序性并不是说一个HashSet对象每次打印时候,顺序是随机的;
  3. 而是说,当插入一个HashSet对象时,其插入的顺序和存储(打印)的顺序是不一样的。

我们来看看下面具体的测试代码:

package set;

import java.util.HashSet;

import org.apache.commons.lang.builder.CompareToBuilder;

public class HashSetTest {

	public static void main(String a[]) {

		 testcase1: HashSet 里面包含了String对象,
		// 因为String已经重写了hashCode(),所以不管插入到HashSet的顺序如何,其存储(打印)顺序是按照hashCode()的实现方式,规定好的
		HashSet<String> stringHashSet = new HashSet<String>();
		for (int i = 0; i < 5; i++) {
			String str = "a" + i;
			stringHashSet.add(str);
		}
		// 每次创建出来的stringHashSet,其打存储(印顺)序不变!
		System.out.println(stringHashSet); // (你会发现打印顺序都是升序的,感觉和String的hashCode()的实现方式有关。)

		
		
		// testcas2: HashSet 里面包含了Cat自定义对象,Cat本身的Comparable功能失效
		// 因为Cat没有重写了hashCode(),所以不管插入到HashSet的顺序如何,其存储(打印)顺序是总是随机的!
		HashSet<Cat> catHashSet = new HashSet<Cat>();
		for (int i = 0; i < 5; i++) {
			Cat p = new Cat("c" + i, i);
			catHashSet.add(p);
		}

		// 每次创建出来的catHashSet,存储(打印)的顺序与插入的顺序不同
		System.out.println(catHashSet);
		System.out.println(catHashSet); // 再次打印同一个对象(catHashSet)的时候,顺序就不会变了
		System.out.println(catHashSet); // 再次打印同一个对象(catHashSet)的时候,顺序就不会变了

		
		
		
		
		/ testcas3: HashSet 里面包含了Person自定义对象,Person本身的Comparable功能失效
		// 因为Person已经重写了hashCode(),所以不管插入到HashSet的顺序如何,其存储(打印)顺序是按照hashCode()的实现方式,规定好的
		HashSet<Person1> personHashSet = new HashSet<Person1>();
		for (int i = 0; i < 5; i++) {
			Person1 p = new Person1("p" + i, i);
			personHashSet.add(p);
		}
		// 每次创建出来的personHashSet,其打存储(印顺)序不变!
		System.out.println(personHashSet);// (你会发现打印顺序都是固定顺序的,感觉和Person的hashCode()的实现方式有关。)

	}
}

class Cat implements Comparable<Cat> {

	public Cat(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}

	private String name;
	private Integer age;

	@Override
	public int compareTo(Cat o) {
		CompareToBuilder ctb = new CompareToBuilder();
		ctb = ctb.append(this.getName(), o.getName()).append(this.getAge(), o.getAge());
		return 0;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	@Override
	public String toString() {
		return "Cat [name=" + name + ", age=" + age + "]";
	}
}

class Person implements Comparable<Person> {
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((age == null) ? 0 : age.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person other = (Person) obj;
		if (age == null) {
			if (other.age != null)
				return false;
		} else if (!age.equals(other.age))
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}

	private String name;
	private Integer age;

	public Person(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	@Override
	public int compareTo(Person o) {
		CompareToBuilder ctb = new CompareToBuilder();
		ctb = ctb.append(this.getName(), o.getName()).append(this.getAge(), o.getAge()); // ASC
																							// 升序
		return ctb.toComparison();
	}

}







LinkedHashSet

是有序的,与HashSet比较来说,插入的顺序和存储(打印)的顺序是一样的


TreeSet

保证集中的元素是有序的,有2种方法可以实现对象之间的可比较性:

1,添加到TreeSet的对象实现了Comparable接口

2,给规则集的元素指定一个比较器(Comparator)

具体实现如下:


package set;

import java.util.Comparator;
import java.util.HashSet;
import java.util.TreeSet;

import org.apache.commons.lang.builder.CompareToBuilder;

public class TreeSetTest {

	public static void main(String a[]) {

		HashSet<Person> hashSet = new HashSet<Person>();
		for (int i = 0; i < 5; i++) {
			Person p = new Person("a" + i, i);
			hashSet.add(p);
		}

		System.out.println(hashSet);

		// 使用TreeSet无参的构造方法,则应用Person实现Comparable接口的compareTo()
		TreeSet<Person> treeSet = new TreeSet<Person>();

		for (int i = 0; i < 5; i++) {
			Person p = new Person("a" + i, i);
			treeSet.add(p);
		}

		System.out.println(treeSet);

		// TreeSet 如果想应用Comparator
		// 得在构造方法传入,这样一来Person实现Comparable接口的compareTo()方法,就失效了
		// 这一点和List使用Comparator不同: Collections.sort(personList, new
		// PersonComparator<Persion>());
		treeSet = new TreeSet<Person>(new PersonComparator());

		for (int i = 0; i < 5; i++) {
			Person p = new Person("a" + i, i);
			treeSet.add(p);
		}

		System.out.println(treeSet);

	}
}

class PersonComparator implements Comparator<Person> {

	@Override
	public int compare(Person o1, Person o2) {

		// 这里使用org.apache.commons.lang.builder.CompareToBuilder,非常好用哦!!!!!
		CompareToBuilder ctb = new CompareToBuilder();

		ctb = ctb.append(o2.getName(), o1.getName()).append(o2.getAge(), o1.getAge()); // DESC
																						// 降序
		// ctb = ctb.append(o1.getName(), o2.getName()).append(o1.getAge(),
		// o2.getAge()); // ASC 升序:注意 o1 o2的先后顺序的变化

		return ctb.toComparison();

	}

}

class Person1 implements Comparable<Person1> {
	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((age == null) ? 0 : age.hashCode());
		result = prime * result + ((name == null) ? 0 : name.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Person1 other = (Person1) obj;
		if (age == null) {
			if (other.age != null)
				return false;
		} else if (!age.equals(other.age))
			return false;
		if (name == null) {
			if (other.name != null)
				return false;
		} else if (!name.equals(other.name))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "Person [name=" + name + ", age=" + age + "]";
	}

	private String name;
	private Integer age;

	public Person1(String name, Integer age) {
		super();
		this.name = name;
		this.age = age;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	@Override
	public int compareTo(Person1 o) {
		CompareToBuilder ctb = new CompareToBuilder();
		ctb = ctb.append(this.getName(), o.getName()).append(this.getAge(), o.getAge()); // ASC
																							// 升序
		return ctb.toComparison();
	}

}







  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值