关于 Java Collections API 您不知道的 5 件事,第 2 部分:注意可变对象
2010-06-23 00:00:00 来源:WEB开发网很显然,这种方法很糟糕,但是解决方法也很简单:永远不要将可变对象类型用作 HashMap 中的键。
5. equals() 与 Comparable
在浏览 Javadoc 时,Java 开发人员常常会遇到 SortedSet 类型(它在 JDK 中唯一的实现是 TreeSet)。因为 SortedSet 是 java.util 包中唯一提供某种排序行为的 Collection,所以开发人员通常直接使用它而不会仔细地研究它。清单 4 展示了:
清单 4. SortedSet,我很高兴找到了它!
import java.util.*;
public class UsingSortedSet
{
public static void main(String[] args)
{
List<Person> persons = Arrays.asList(
new Person("Ted", "Neward", 39),
new Person("Ron", "Reynolds", 39),
new Person("Charlotte", "Neward", 38),
new Person("Matthew", "McCullough", 18)
);
SortedSet ss = new TreeSet(new Comparator<Person>() {
public int compare(Person lhs, Person rhs) {
return lhs.getLastName().compareTo(rhs.getLastName());
}
});
ss.addAll(perons);
System.out.println(ss);
}
}
使用上述代码一段时间后,可能会发现这个 Set 的核心特性之一:它不允许重复。该特性在 Set Javadoc 中进行了介绍。Set 是不包含重复元素的集合。更准确地说,set 不包含成对的 e1 和 e2 元素,因此如果 e1.equals(e2),那么最多包含一个 null 元素。
但实际上似乎并非如此 — 尽管 清单 4 中没有相等的 Person 对象(根据 Person 的 equals() 实现),但在输出时只有三个对象出现在 TreeSet 中。
与 set 的有状态本质相反,TreeSet 要求对象直接实现 Comparable 或者在构造时传入 Comparator,它不使用 equals() 比较对象;它使用 Comparator/Comparable 的 compare 或 compareTo 方法。
因此存储在 Set 中的对象有两种方式确定相等性:大家常用的 equals() 方法和 Comparable/Comparator 方法,采用哪种方法取决于上下文。
更糟的是,简单的声明两者相等还不够,因为以排序为目的的比较不同于以相等性为目的的比较:可以想象一下按姓排序时两个 Person 相等,但是其内容却并不相同。
一定要明白 equals() 和 Comparable.compareTo() 两者之间的不同 — 实现 Set 时会返回 0。甚至在文档中也要明确两者的区别。
结束语
Java Collections 库中有很多有用之物,如果您能加以利用,它们可以让您的工作更轻松、更高效。但是发掘这些有用之物可能有点复杂,比如只要您不将可变对象类型作为键,您就可以用自己的方式使用 HashMap。
至此我们挖掘了 Collections 的一些有用特性,但我们还没有挖到金矿:Concurrent Collections,它在 Java 5 中引入。本 系列 的后 5 个窍门将关注 java.util.concurrent。
本文示例源代码或素材下载
Tags:关于 Java Collections
编辑录入:爽爽 [复制链接] [打 印]更多精彩
赞助商链接