18.JAVA编程思想——使用Sets
Set 拥有与Collection 完全相同的接口,所以和两种不同的List 不同,它没有什么额外的功能。相反,Set完全就是一个Collection,只是具有不同的行为(这是实例和多形性最理想的应用:用于表达不同的行为)。在这里,一个Set 只允许每个对象存在一个实例。
Set(接口) 添加到Set 的每个元素都必须是独一无二的;否则Set 就不会添加重复的元素。添加到Set 里的对象必须定义equals(),从而建立对象的唯一性。Set 拥有与Collection 完全相同的接口。一个Set 不能保证自己可按任何特定的顺序维持自己的元素
HashSet* 用于除非常小的以外的所有Set。对象也必须定义hashCode()
ArraySet 由一个数组后推得到的Set。面向非常小的Set 设计,特别是那些需要频繁创建和删除的。对于小Set,与HashSet 相比,ArraySet 创建和反复所需付出的代价都要小得多。但随着Set 的增大,它的性能也会大打折扣。不需要HashCode()
TreeSet 由一个“红黑树”后推得到的顺序Set。这样一来,我们就可以从一个Set 里提到一个
顺序集合。
1 代码如下:
import java.util.*;
public class Set1 {
public staticvoidtestVisual(Set a) {
Collection1.fill(a);
Collection1.fill(a);
Collection1.fill(a);
Collection1.print(a); // No duplicates!
// Add another set to this one:
a.addAll(a);
a.add("one");
a.add("one");
a.add("one");
Collection1.print(a);
// Look something up:
System.out.println("a.contains(\"one\"): "+ a.contains("one"));
}
public staticvoidmain(String[] args){
testVisual(new HashSet());
testVisual(new TreeSet());
}
} /// :~
2 运行如下:
01 2 3 4 5 6 7 8 9
01 2 3 4 5 6 7 one 8 9
a.contains("one"):true
01 2 3 4 5 6 7 8 9
01 2 3 4 5 6 7 8 9 one
a.contains("one"):true
3 代码解释
重复的值被添加到Set,但在打印的时候,我们会发现Set 只接受每个值的一个实例。
运行这个程序时,会注意到由HashSet 维持的顺序与ArraySet 是不同的。这是由于它们采用了不同的方法来保存元素,以便它们以后的定位。ArraySet保持着它们的顺序状态,而HashSet 使用一个散列函数,这是特别为快速检索设计的)。创建自己的类型时,一定要注意Set 需要通过一种方式来维持一种存储顺序。
4 代码2如下:
import java.util.*;
class MyType implements Comparable {
private inti;
public MyType(intn) {
i = n;
}
public booleanequals(Object o) {
return (o instanceof MyType) && (i == ((MyType) o).i);
}
public inthashCode() {
return i;
}
public String toString() {
return i + " ";
}
public intcompareTo(Object o){
int i2 = ((MyType) o).i;
return (i2 < i ? -1 : (i2 == i ? 0 : 1));
}
}
public class Set2 {
public staticSet fill(Set a, intsize){
for (int i = 0; i < size; i++)
a.add(new MyType(i));
return a;
}
public staticSet fill(Set a) {
return fill(a, 10);
}
public staticvoidtest(Set a){
fill(a);
fill(a); // Try to addduplicates
fill(a);
a.addAll(fill(new TreeSet()));
System.out.println(a);
}
public staticvoidmain(String[] args){
test(new HashSet());
test(new TreeSet());
}
} /// :~
5 执行如下
[0, 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ]
[9, 8 , 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 ]
6 代码解释如下
对equals() 及hashCode()的定义都必须定义一个equals()。但只有要把类置入一个HashSet 的前提下,才有必要使用hashCode()——这种情况是完全有可能的,因为通常应先选择作为一个Set 实现。