Set 集合不允许包含相同的元素,如果试把两个相同的元素加入同一个 Set 集合中,则添加操作失败。
Set 判断两个对象是否相同不是使用 == 运算符,而是根据 equals 方法。
Set实现类:HashSet、LinkedHashSet、TreeSet
HashSet:通过散列表存信息,无序存储,元素必须定义hashCode();
LinkedHashSet:内部使用链表维护元素顺序,按顺序插入顺序排序,也必须定义hashCode();
TreeSet:通过树结构(和TreeMap一致,使用红黑树)存储元素,存储数据有序。
HashSet :
1、当向 HashSet 集合中存入一个元素时,HashSet 会调用该对象的 hashCode() 方法来得到该对象的hashCode 值, 然后根据 hashCode 值决定该对象在 HashSet 中的存储位置。
2、如果两个元素的 equals() 方法返回 true,但它们的 hashCode() 返回值不相等,hashSet 将会把它们存储在不同的位置,但依然可以添加成功。
3、HashSet 集合判断两个元素相等的标准:两个对象通过 equals() 方法比较相等,并且两个对象的hashCode() 方法返回值也相等。即:如果两个对象通过 equals() 方法返回 true,这两个对象的hashCode 值也应该相同。
重写 hashCode() 方法的基本原则:
1、在程序运行时,同一个对象多次调用 hashCode() 方法应该返回相同的值。
2、当两个对象的 equals() 方法比较返回 true 时,这两个对象的 hashCode() 方法的返回值也应相等。
3、对象中用作 equals() 方法比较的 Field,都应该用来计算 hashCode 值。
LinkedHashSet :
1、LinkedHashSet 是 HashSet 的子类。
2、LinkedHashSet 集合根据元素的 hashCode 值来决定元素的存储位置,但它同时使用链表维护元素的次序,这使得元素看起来是以插入顺序保存的。
3、LinkedHashSet 性能插入性能略低于 HashSet,但在迭代访问 Set 里的全部元素时有很好的性能。
4、LinkedHashSet 有序但不允许集合元素重复。
TreeSet:
TreeSet 是 SortedSet 接口的实现类,TreeSet 可以确保集合元素处于排序状态。
TreeSet 支持两种排序方法:自然排序和定制排序。默认情况下,TreeSet 采用自然排序。
排序:
1、TreeSet 会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系,
然后将集合元素按升序排列。
2、如果试图把一个对象添加到 TreeSet 时,则该对象的类必须实现 Comparable 接口。
3、实现 Comparable 的类必须实现 compareTo(Object obj) 方法,两个对象即通过
compareTo(Object obj)方法的返回值来比较大小。
注意:
向 TreeSet 中添加的应该是同一个类的对象,
当需要把一个对象放入 TreeSet 中,重写该对象对应的 equals() 方法时,应保证该方法与
compareTo(Object obj) 方法有一致的结果:即如果两个对象通过 equals() 方法比较返回 true,
则通过 compareTo(Object obj) 方法比较应返回 0。
自然排序:
import java.util.*;
/*
TreeSet:可以对Set集合中的元素进行排序。
底层数据结构是二叉树。
保证元素唯一性的依据:
compareTo方法return 0.
TreeSet排序的第一种方式:让元素自身具备比较性。
元素需要实现Comparable接口,覆盖compareTo方法。
也种方式也成为元素的自然顺序,或者叫做默认顺序。
TreeSet的第二种排序方式。
当元素自身不具备比较性时,或者具备的比较性不是所需要的。
这时就需要让集合自身具备比较性。
在集合初始化时,就有了比较方式。
需求:
往TreeSet集合中存储自定义对象学生。
想按照学生的年龄进行排序。
记住,排序时,当主要条件相同时,一定判断一下次要条件。
*/
class Treeset {
public static void main(String[] args) {
Set ts = new TreeSet();
ts.add(new Student("lisi02", 22));
ts.add(new Student("lisi007", 20));
ts.add(new Student("lisi09", 19));
ts.add(new Student("lisi08", 19));
// ts.add(new Student("lisi007",20));
// ts.add(new Student("lisi01",40));
Iterator it = ts.iterator();
while (it.hasNext()) {
Student stu = (Student) it.next();
System.out.println(stu.getName() + "..." + stu.getAge());
}
}
}
class Student implements Comparable// 该接口强制让学生具备比较性。
{
private String name;
private int age;
Student(String name, int age) {
this.name = name;
this.age = age;
}
public int compareTo(Object obj) {
// return 0;
if (!(obj instanceof Student))
throw new RuntimeException("不是学生对象");
Student s = (Student) obj;
System.out.println(this.name + "....compareto....." + s.name);
if (this.age > s.age)
return 1;
if (this.age == s.age) {
return this.name.compareTo(s.name);
}
return -1;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
}
定制排序:
import java.util.*;
/*
当元素自身不具备比较性,或者具备的比较性不是所需要的。
这时需要让容器自身具备比较性。
定义了比较器,将比较器对象作为参数传递给TreeSet集合的构造函数。
当两种排序都存在时,以比较器为主。
定义一个类,实现Comparator接口,覆盖compare方法。
*/
class Student implements Comparable//该接口强制让学生具备比较性。
{
private String name;
private int age;
Student(String name,int age)
{
this.name = name;
this.age = age;
}
public int compareTo(Object obj)
{
//return 0;
if(!(obj instanceof Student))
throw new RuntimeException("不是学生对象");
Student s = (Student)obj;
//System.out.println(this.name+"....compareto....."+s.name);
if(this.age>s.age)
return 1;
if(this.age==s.age)
{
return this.name.compareTo(s.name);
}
return -1;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
class TreeSetDemo2
{
public static void main(String[] args)
{
Set ts = new TreeSet();
ts.add(new Student("lisi02",22));
ts.add(new Student("lisi02",21));
ts.add(new Student("lisi007",20));
ts.add(new Student("lisi09",19));
ts.add(new Student("lisi06",18));
ts.add(new Student("lisi06",18));
ts.add(new Student("lisi007",29));
//ts.add(new Student("lisi007",20));
//ts.add(new Student("lisi01",40));
Iterator it = ts.iterator();
while(it.hasNext())
{
Student stu = (Student)it.next();
System.out.println(stu.getName()+"..."+stu.getAge());
}
}
}
class MyCompare implements Comparator
{
public int compare(Object o1,Object o2)
{
Student s1 = (Student)o1;
Student s2 = (Student)o2;
int num = s1.getName().compareTo(s2.getName());
if(num==0)
{
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
/*
if(s1.getAge()>s2.getAge())
return 1;
if(s1.getAge()==s2.getAge())
return 0;
return -1;
*/
}
return num;
}
}
性能分析:可以参考《Thinking in java》,数据如下:
------------- TreeSet -------------
size add contains iterate
10 1316 506 180
100 199 101 22
1000 250 174 19
10000 266 224 21
------------- HashSet -------------
size add contains iterate
10 1717 325 242
100 59 16 43
1000 66 25 27
10000 66 28 25
---------- LinkedHashSet ----------
size add contains iterate
10 516 151 72
100 127 40 29
1000 145 57 27
10000 125 53 25
可以看出HashSet性能基本总比TreeSet好 ,除非确定需要排序时,才该使用TreeSet。
该博客仅作为复习记录。
本文大多数参考:http://www.cnblogs.com/shellway/p/3709074.html