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里提到一个顺序集合 ⑦直至本书写作的时候TreeSet仍然只是宣布尚未正式实现所以这里没有提供使用TreeSet的例子 下面这个例子并没有列出用一个Set能够做的全部事情因为接口与Collection是相同的前例已经练习过了相反我们要例示的重点在于使一个Set独一无二的行为 //: Setjava // Things you can do with Sets package cnewcollections; import javautil*; public class Set { public static void testVisual(Set a) { Collectionfill(a); Collectionfill(a); Collectionfill(a); Collectionprint(a); // No duplicates! // Add another set to this one: aaddAll(a); aadd(one); aadd(one); aadd(one); Collectionprint(a); // Look something up: Systemoutprintln(ntains(\one\): + ntains(one)); } public static void main(String[] args) { testVisual(new HashSet()); testVisual(new TreeSet()); } } ///:~ 重复的值被添加到Set但在打印的时候我们会发现Set只接受每个值的一个实例 运行这个程序时会注意到由HashSet维持的顺序与ArraySet是不同的这是由于它们采用了不同的方法来保存元素以便它们以后的定位ArraySet保持着它们的顺序状态而HashSet使用一个散列函数这是特别为快速检索设计的)创建自己的类型时一定要注意Set需要通过一种方式来维持一种存储顺序就象本章早些时候展示的groundhog(土拔鼠)例子那样下面是一个例子 //: Setjava // Putting your own type in a Set package cnewcollections; import javautil*; class MyType implements Comparable { private int i; public MyType(int n) { i = n; } public boolean equals(Object o) { return (o instanceof MyType) && (i == ((MyType)o)i); } public int hashCode() { return i; } public String toString() { return i + ; } public int compareTo(Object o) { int i = ((MyType) o)i; return (i < i ? -1 : (i2 == i ? 0 : 1)); } } public class Set2 { public static Set fill(Set a, int size) { for(int i = 0; i < size; i++) a.add(new MyType(i)); return a; } public static Set fill(Set a) { return fill(a, 10); } public static void test(Set a) { fill(a); fill(a); // Try to add duplicates fill(a); a.addAll(fill(new TreeSet())); System.out.println(a); } public static void main(String[] args) { test(new HashSet()); test(new TreeSet()); } } ///:~ 对equals()及hashCode()的定义遵照“groundhog”例子已经给出的形式。tW.WinGWit.cOm在两种情况下都必须定义一个equals()。但只有要把类置入一个HashSet的前提下,才有必要使用hashCode()——这种情况是完全有可能的,因为通常应先选择作为一个Set实现。 |