| |
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独一无二的行为: //: set1.java // things you can do with sets package c08.newcollections; import java.util.*; public class set1 { public static void testvisual(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 static void main(string[] args) { testvisual(new hashset()); testvisual(new treeset()); } } ///:~ 重复的值被添加到set,但在打印的时候,我们会发现set只接受每个值的一个实例。 运行这个程序时,会注意到由hashset维持的顺序与arrayset是不同的。这是由于它们采用了不同的方法来保存元素,以便它们以后的定位。arrayset保持着它们的顺序状态,而hashset使用一个散列函数,这是特别为快速检索设计的)。创建自己的类型时,一定要注意set需要通过一种方式来维持一种存储顺序,就象本章早些时候展示的“groundhog”(土拔鼠)例子那样。下面是一个例子: //: set2.java // putting your own type in a set package c08.newcollections; import java.util.*; 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 i2 = ((mytype) o).i; return (i2 < 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”例子已经给出的形式。在两种情况下都必须定义一个equals()。但只有要把类置入一个hashset的前提下,才有必要使用hashcode()——这种情况是完全有可能的,因为通常应先选择作为一个set实现。
|
|