首先说,Set是一个接口,在看其原码的时候,看到Set接口继承了Collection接口。然而,Set接口和Collection接口中定义的方法几乎完全一样和,除了有default修饰的方法不一样之外。可以看出,Set接口具有与Collection接口几乎完全一样的性质。事实上,Set就是Collection,只是行为不同。
Set集合不保存重复的元素。如果你想把相同对象的多个实例添加到Set中,它会阻止你这种操作。Set中最常被使用的是用它来检测归属性,也就是,可以用来测试一个对象是否在这个Set中。也正是这样,查找就成了Set中最重要的操作,我们用的最多的就是HashSet,因为它专门对快速查找进行了优化。
但是,Set接口的实现类可不止它一个。下图表示了Set集合与上下层之间的关系。
其中,HashSet所维护的顺序与TreeSet或LinkedHashSet都不同,因为它们的实现具有不同的元素存储方式。TreeSet将元素存储在红—黑树数据结构中,而HashSet使用的是散列函数。LinkedHashSet因为查询速度的原因也使用了散列,但是看起来它使用了链表来维护元素的插入顺序。
对于存储Java预定义的类型,如String,Integer类型等,这些可以直接在Set对象中进行操作。但是,当我们想操作自己创建的类时,要意识到Set需要一种方式来维护存储顺序,而存储顺序如何维护,则是在Set的不同实现之间会有所变化。因此,不同的Set实现不仅具有不同的行为,而且它们对于可以在特定的Set中放置的元素的类型也有不同的要求:
上述的TreeSet是指按照Comparable接口所实现的方法对元素进行排序,不是指元素的插入顺序。
按照元素的插入顺序排序的是LinkedHashSet。