java集合框架总结三--Set接口及其子类

时间:2021-02-22 17:58:27

Set接口

Set与Collection的结构基本上完全一样,不同在于无序,不能重复

Set判断两个对象相同不是使用==运算符,而是根据equals方法。也就是说两个对象用equals方法比较返回true,Set就不会接受这两个对象。

/**
* Set演示
* 2014-4-6
*/
import java.util.HashSet;
import java.util.Set;
public class SetDemo
{
public static void main(String[] args)
{
Set s
=new HashSet();
s.add(
"123");
//添加两个相同的元素,会返回false
boolean m=s.add("123");
System.out.println(m);
System.out.println(s);
}
}

程序运行结果:

 

false
[
123]

HashSet

内部结构为哈希表

元素无序,不是同步的(注意线程安全问题),集合元素值可以为null

当向 HashSet集合中存入一个元素时,HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,然后根据该值来决定该对象在HashSet中的存储位置。如果有两个元素通过equals方法比较返回true,但它们的hashCode方法返回值不相等,HashSet将会把它们存储在不同的位置。也就是说HashSet集合判断两个元素相等的标准是两个对象通过equals方法比较相等,并且两个对象的hashCode方法返回值也相等。

import java.util.HashSet;
/**
* HashSet类判断两元素相等实例
* 2014-4-6
*
@author Administrator
*
*/
public class HashSetDemo {

/**
*
@param args
*/
public static void main(String[] args) {

HashSet set
=new HashSet();
set.add(
new A());
set.add(
new A());
set.add(
new B());
set.add(
new B());
set.add(
new C());
set.add(
new C());
System.out.println(set);

}
}
class A{
@Override
public boolean equals(Object obj){
return true;
}
}

class B{
@Override
public int hashCode(){
return 1;
}
}

class C{
@Override
public int hashCode(){
return 2;
}
public boolean equals(Object obj){
return true;
}
}

程序运行结果:

[B@1, B@1, C@2, A@4f1d0d, A@18a992f]

Object类提供的toString方法总是返回该对象实现类的类名+@+hashCode(16进制数)值,所以可以看到上面程序输出的结果。可以通过重写toString方法来输出自己希望的形式。

即使2个A对象通过equals比较返回true,但HashSet依然把它们当成2个对象;即使2个B对象的hashCode()返回相同值,但HashSet依然把它们当成2个对象。即如果把一个对象放入HashSet中时,如果重写该对象equals()方法,也应该重写其hashCode()方法。其规则是:如果2个对象通过equals方法比较返回true时,这两个对象的hashCode也应该相同。

TreeSet:

以对集合中的元素进行排序。是不同步的

TreeSet支持两种排序方法:自然排序和定制排序。默认情况下TreeSet采用自然排序

自然排序

TreeSet会调用集合元素的comparaTo(Object obj)方法来比较元素之间大小关系,然后将集合元素按升序排列,这就是自然排序。
Java提供了一个Comparable接口,该接口中定义了一个comparaTo(Object obj)方法,返回一个整数值,实现了该接口的类的对象就可以比较大小。如:obj1.comparaTo(obj2),如果该方法返回0,则表明这两个对象相等;返回正整数,则表明obj1大于obj2;返回一个负整数,则表明obj1小于obj2。

如果试图把一个对象添加进TreeSet时,则该对象的类必须实现CompareTo接口,否则程序将会出现异常

import java.util.TreeSet;

/**
* TreeSetTreeSet添加两个相同类型的对象错误示范
* 2014-4-7
*
@author Administrator
*
*/
public class TreeSetDemo {

/**
*
@param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TreeSet set=new TreeSet();
set.add(
new Error());
//添加两个相同元素,会引发java.lang.ClassCastException异常
set.add(new Error());

}
}

class Error{

}

向TreeSet集合中添加元素时,只有第一个元素可以无需实现CompareTo接口,后面添加的所有元素都必须实现CompareTo接口。另外向TreeSet中添加的应该是同一个类的对象,不然不好比较,否则也会引发ClassCastException异常。
对于TreeSet集合而言,它判断两个对象不相等的标准是:两个对象通过equals方法比较返回false,或通过compareTo比较没有返回0,即使两个对象是同一个对象,TreeSet也会把他们当成两个对象处理。

import java.util.TreeSet;

/**
* TreeSet添加两个相同类型的对象示范
* 2014-4-7
*
@author Administrator
*
*/
public class TreeSetDemo2 {

/**
*
@param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
TreeSet set=new TreeSet();
Z z
=new Z(10);
set.add(z);
boolean flag=set.add(z);
System.out.println(flag);
System.out.println(set);

}
}

class Z implements Comparable{
int age;
public Z(int age){
this.age=age;
}
public boolean Equals(Object obj){
return false;
}
public int compareTo(Object o) {
// TODO Auto-generated method stub
return 1;
}
}

定制排序

使用定制排序时,TreeSet对集合元素排序时不管集合元素本身大小,而是由Comparator对象负责集合元素的排序规则。