首页 > 代码库 > Java学习笔记_22_Set接口的实现类

Java学习笔记_22_Set接口的实现类

22.Set接口的实现类:

 Set接口存放的元素是无序的且不包含重复元素。

 1>实现类HashSet:

  HashSet类根据元素的哈希码进行存放,取出时也可以根据哈希码快速找到。HashSet不保存元素的添加的顺序。

 例子:

 import java.util.HashSet;
 import java.util.Iterator;

 public class Student {
 
	public static void main(String[] args) {

		HashSet<String> hs = new HashSet<String>();
		
		hs.add("1 zxx");
		hs.add("1 zxx");
		hs.add("2 hahx");
		hs.add("3 zyj");
		hs.add("4 bmh");

		Iterator<String> it = hs.iterator();
		while (it.hasNext()) {
			System.out.println(it.next());
		}
	}
 }

输出结果:

 1 zxx

 4 bmh

 3 zyj

 2 hahx

因为Set集合中不能存放重复的元素,所以对于自定义的类,要重写hashCode()和equals()方法,用来判断元素是否为重复对象。

例子:

public class Student {

	private int age;
	private String name;

	// get、set方法省略
	
	public Student(int age, String name) {
		this.age = age;
		this.name = name;
	}

	
       // 重写HashCode方法
	public int hashCode() {
		return age * name.hashCode();
	}

	// 重写equals方法
	public boolean equals(Object obj) {
		Student s = (Student) obj;
		return age == s.age && name.equals(s.name);
	}
}

注:如果两个对象相同,那么它们的hashCode值一定要相同;如果两个对象的hashCode值相同,他们并不一定相同。 

2>实现类LinkedHashSet:

 LinkHashSet类根据元素的哈希码进行存放,同时用链表记录元素的加入顺序。 

 简单的字符集合例子:

import java.util.Iterator;
 import java.util.LinkedHashSet;

 public class TestLinkedHashSet {
	 public static void main(String[] args) {
		//创建一个LinkedHashSet集合对象
		LinkedHashSet<String> lhs = new LinkedHashSet<String>();
		//向集合对象中添加字符串
		lhs.add("zxx");
		lhs.add("abc");
		lhs.add("hik");
		lhs.add("hik");
		lhs.add(null);
		//生成一个迭代器
		Iterator<String> it =  lhs.iterator();
		//输出字符串
		while(it.hasNext()){
			System.out.println(it.next());
		}
	  }
   } 

输出为:

zxx

abc

hik

Null

自定义对象的集合使用例子:

创建Student类:

public class Student {
	//创建属性
	private int age;
	private String name;
	//生成属性的get和set方法
	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;
	}
	//包含参数的构造函数
	public Student(int age, String name) {
		this.age = age;
		this.name = name;
	}
	//重写toString方法
	public String toString() {
		return "age :" + age + " name :" + name;
	}
	
    // 重写HashCode方法
	public int hashCode() {
		return age * name.hashCode();
	}

	// 重写equals方法
	public boolean equals(Object obj) {
		Student s = (Student) obj;
		return age == s.age && name.equals(s.name);
	}
}

 测试LinkedHashSet的主函数:

import java.util.Iterator;
import java.util.LinkedHashSet;

public class TestLinkedHashSet {
	public static void main(String[] args) {
		//创建一个LinkedHashSet集合对象
		LinkedHashSet<Student> lhs = new LinkedHashSet<Student>();
		//生成一些Student对象
		Student sd1 = new Student(18, "zxx");
		Student sd2 = new Student(23, "abc");
		Student sd3 = new Student(25, "hik");
		Student sd4 = new Student(25, "hik");
		//向集合对象中添加Student对象
		lhs.add(sd4);
		lhs.add(sd2);
		lhs.add(sd3);
		lhs.add(sd1);
		lhs.add(null);
		//生成一个迭代器
		Iterator<Student> it = lhs.iterator();
		//输出字符串
		while (it.hasNext()) {
			System.out.println(it.next());
		}
	}
}

输出:

age :25 name :hik

age :23 name :abc

age :18 name :zxx

null

注:通过链表来存储对象,一般插入和删除效率比较高,检索效率相对较低。

3>实现类TreeSet:

 TreeSet的构造方法:

 · TreeSet(): 构造一个空树集。

 · TreeSet(Collection c): 构造一个树集,并添加集合c中的所有元素。

 · TreeSet(Comparator c): 构造一个树集,并且使用特定的比较器对其经行排序。

 · TreeSet(SortedSet s): 构造一个树集,添加有序集合s中的所有元素,并且使用与有序集s相同的比较器排序。

 注意:放入TreeSet中的元素必须是可以排序的。假若要对加入的Student类经行排序,

            则要实现compareTo()方法,那么就必须实现Comparable接口。


 排序Student集合类例子:

 Student中的代码:

public class Student implements Comparable {
	// 创建属性
	private Integer age;
	private String name;

	// 包含参数的构造函数
	public Student(Integer age, String name) {
		this.age = age;
		this.name = name;
	}

	// 生成属性的get和set方法
	public Integer getAge() {
		return age;
	}

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

	public String getName() {
		return name;
	}

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

	// 重写toString方法
	public String toString() {
		return "age :" + age + " name :" + name;
	}

	// 重写HashCode方法
	public int hashCode() {
		return age * name.hashCode();
	}

	// 重写equals方法
	public boolean equals(Object obj) {
		Student s = (Student) obj;
		return age == s.age && name.equals(s.name);
	}

	//重写compareTo(Object o)方法
	public int compareTo(Object o) {
		Student s = (Student) o;
		if (s.getAge().compareTo(this.getAge()) > 0)
			return -1;
		else if (s.getAge().compareTo(this.age) == 0)
			return 0;
		else
			return 1;
	}
 }
 

TestTreeSet类中的代码:

import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

public class TestTreeSet {
	public static void main(String[] args) {
		// 创建一个LinkedHashSet集合对象
		Set<Student> ts = new TreeSet<Student>();
		// 生成一些Student对象
		Student sd1 = new Student(18, "zxx");
		Student sd2 = new Student(23, "abc");
		Student sd3 = new Student(25, "hik");
		Student sd4 = new Student(25, "hik");
		Student sd5 = new Student(17, "cde");
		// 向集合对象中添加Student对象
		lhs.add(sd4);
		ts.add(sd2);
		ts.add(sd5);
		ts.add(sd3);
		ts.add(sd1);
		// 生成一个迭代器
		Iterator<Student> it = ts.iterator();
		// 输出字符串
		while (it.hasNext()) {
			System.out.println(it.next());
		}
	 }
  }

输出结果:

age :17 name :cde

age :18 name :zxx

age :23 name :abc

age :25 name :hik

很明显TreeSet中的Student类按age由小到大的顺序排序。

使用Comparable接口可以完成TreeSet的排序,但使用Comparable接口定义排序具有局限性,

实现此接口的类只能按CompareTo()定义的这一种方法排序。如果同一类对象要有多种排序方式,

应该为该类定义不同的比较器。定义比较器实际上就是让自编写的类实现Comparator接口,

重写Comparator接口中的比较方法compare(Object a,Object b)。


排序Student集合类例子:

Student中的代码:

public class Student {
	// 创建属性
	private Integer age;
	private String name;
	private Integer score;

	// 包含参数的构造函数
	public Student(Integer age, String name, Integer score) {
		this.age = age;
		this.name = name;
		this.score = score;
	}

	// 重写toString方法
	public String toString() {
		return "name :" + name + " age :" + age + " score :" + score;
	}

	// 生成属性的get和set方法
	public Integer getAge() {
		return age;
	}

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

	public String getName() {
		return name;
	}

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

	public Integer getScore() {
		return score;
	}

	public void setScore(Integer score) {
		this.score = score;
	}

	// 重写HashCode方法
	public int hashCode() {
		return age * score * name.hashCode();
	}

	// 重写equals方法
	public boolean equals(Object obj) {
		Student s = (Student) obj;
		return age == s.age && name.equals(s.name)
                && score == s.score;
	}
 }

TestTreeSet类中的代码:

import java.util.Comparator;
import java.util.Iterator;
import java.util.Set;
import java.util.TreeSet;

//学生年龄比较器
class StudentAgeComparator implements Comparator<Student> {
	public int compare(Student o1, Student o2) {
		int i = o1.getAge() - o2.getAge();
		return i;
	}
}

// 学生成绩比较器
class StudentScoreComparator implements Comparator<Student> {
	public int compare(Student o1, Student o2) {
		int i = o1.getScore() - o2.getScore();
		return i;
	}
}

public class TestTreeSet {
	public static void main(String[] args) {
		// 创建一个LinkedHashSet集合对象
		//按年龄有小到大排顺序
		Set<Student> ts = new TreeSet<Student>(new  
                                             StudentAgeComparator());
		//按成绩由小到大排序
              //Set<Student> ts = new TreeSet<Student>(new 
                                             StudentScoreComparator());
		
		// 生成一些Student对象
		Student sd1 = new Student(18, "zxx", 60);
		Student sd2 = new Student(23, "abc", 85);
		Student sd3 = new Student(25, "hik", 45);
		Student sd4 = new Student(25, "hik", 90);
		Student sd5 = new Student(17, "cde", 33);
		
		// 向集合对象中添加Student对象
		ts.add(sd1);
		ts.add(sd2);
		ts.add(sd3);
		ts.add(sd4);
		ts.add(sd5);
		
		// 生成一个迭代器
		Iterator<Student> it = ts.iterator();
		
		// 输出字符串
		while (it.hasNext()) {
			System.out.println(it.next());
		}
	 }
  }

当选用Set<Student> ts = new TreeSet<Student>(new StudentAgeComparator());时。

输出结果:

name :cde age :17 score :33

name :zxx age :18 score :60

name :abc age :23 score :85

name :hik age :25 score :45

很明显是按年龄由小到大排序的。

当选用Set<Student> ts = new TreeSet<Student>(new StudentScoreComparator());时。

输出结果:

name :cde age :17 score :33
name :hik age :25 score :45
name :zxx age :18 score :60
name :abc age :23 score :85
name :hik age :25 score :90

很明显是按成绩由小到大排序的。