Collections 的排序【转】- -
在使用 Java Collections Framework 时,必须知道 Collections
类中的变量是哪些。这个类包含大量支持集合操作的静态方法。在这里,我们不会对所有方法进行介绍,因为您可以自己阅读 API,但是我们将介绍两个经常出现在 Java 代码中的方法:
第一个方法允许将一个集合的内容复制到另一个集合,如下所示:
List source = new ArrayList();
source.add("one");
source.add("two");
List target = new ArrayList();
target.add("three");
target.add("four");
Collections.copy(target, source);
System.out.println(target);
该代码将 source
复制到 target
中。目标代码的大小必须与源代码的大小相同,这样,就无法将 List
复制到空的 List
中。
sort()
方法元素归类成其自然顺序。所有元素都必须实现 Comparable
接口,这样,它们就可以相互比较。像 String
这样的内置类也已经创建。因此,对于一组字符串而言,可以使用以下代码按照字典顺序的升序顺序对字符串进行排序:
List strings = new ArrayList();
strings.add("one");
strings.add("two");
strings.add("three");
strings.add("four");
Collections.sort(strings);
System.out.println(strings);
您将在控制台中获得 [four, one, three, two]
。但是现在可以对创建的类进行分类吗?可以对 Adult
进行分类。首先要让类进行相互比较:
public class Adult extends Person implements Comparable {
...
}
然后要重写 compareTo()
来比较两个 Adult
实例。我们将保持我们的例子在比较方面的简单性,所以该例不会进行太多的比较操作:
public int compareTo(Object other) {
final int LESS_THAN = -1;
final int EQUAL = 0;
final int GREATER_THAN = 1;
Adult otherAdult = (Adult) other;
if ( this == otherAdult ) return EQUAL;
int comparison = this.firstname.compareTo(otherAdult.firstname);
if (comparison != EQUAL) return comparison;
comparison = this.lastname.compareTo(otherAdult.lastname);
if (comparison != EQUAL) return comparison;
return EQUAL;
}
任何小于 0 的数字都意味着“小于”,但是 -1 是表示这个意思一个很好用的值。与此类似,用 1 表示“大于”也很方便。正如您可以看到的,0 则意味着“等于”。以这种方式比较两个对象显然是一个手动过程。您必须遍历实例变量并比较每个变量。在这种情况下,我们要比较名和姓,并根据姓氏有效地对人们进行排序。但是您应该能够明白为什么我们的例子过于简单。每个 Adult
都只有一个名和姓。如果想进行深层的比较,那么必须比较每个 Adult
的 Wallet
,以查看它们是否相等,这可能意味着我们必须在 Wallet
和其余对象上实现 compareTo()
。此外,为了正确进行比较,无论何时重写 compareTo()
,都必须确保该比较与 equals()
是一致的。我们没有实现 equals()
,所以不用担心要与它一致,但我们可以做到这一点。事实上,在返回 EQUAL
之前,我已经看到包含类似以下代码行的代码:
assert this.equals(otherAdult) : "compareTo inconsistent with equals.";
比较对象的其他方法是:提取 compareTo()
中的算法,将其放入 Comparator
类型的对象中,然后对将分类的集合调用 Collections.sort()
和 Comparator
,如下所示:
public class AdultComparator implements Comparator {
public int compare(Object object1, Object object2) {
final int LESS_THAN = -1;
final int EQUAL = 0;
final int GREATER_THAN = 1;
if ((object1 == null) ;amp;amp (object2 == null))
return EQUAL;
if (object1 == null)
return LESS_THAN;
if (object2 == null)
return GREATER_THAN;
Adult adult1 = (Adult) object1;
Adult adult2 = (Adult) object2;
if (adult1 == adult2)
return EQUAL;
int comparison = adult1.firstname.compareTo(adult2.firstname);
if (comparison != EQUAL)
return comparison;
comparison = adult1.lastname.compareTo(adult2.lastname);
if (comparison != EQUAL)
return comparison;
return EQUAL;
}
}
public class CommunityApplication {
public static void main(String[] args) {
Adult adult1 = new Adult();
adult1.setFirstname("Bob");
adult1.setLastname("Smith");
Adult adult2 = new Adult();
adult2.setFirstname("Al");
adult2.setLastname("Jones");
List adults = new ArrayList();
adults.add(adult1);
adults.add(adult2);
Collections.sort(adults, new AdultComparator());
System.out.println(adults);
}
}
在控制台窗口中,应该看到以某种顺序排列的“Al Jones”和“Bob Smith”。
使用第二种方法是有一些好的理由的。技术方面的理由已经超出了本文的讨论范围。不过,从好的 OOD 的角度来看,将比较代码隔离到另一个对象中,而不是为每个 Adult
提供将自身与其他对象比较的能力是一个好主意。然而,因为这正是 equals()
要做的事,所以即使结果是布尔值,对于每种方法而言,那些仍然是一些好参数。
何时应该使用特殊类型的集合?这是一个由您做出的判断决定,而且,正是因为这类的决定,您希望像一位编程人员那样付出很多。
尽管许多专业人士相信,没有太多关于在任一给定情况下使用哪些类的硬性规定。以我的个人经验而论,大多数时间里,我使用集合、ArrayList
或 HashMap
(请记住,Map
不是真正的集合)获得了成功。您自己去体验可能也会有同样的效果。以下是一些经验法则,其中的一些显然要好于另外一些:
- 在认为自己需要一个集合时,从使用
List
开始,然后让代码告诉您是否需要另一种类型的集合。
- 如果需要惟一的一组什么东西,那么请使用
Set
。
- 在遍历集合时,如果迭代顺序很重要,则使用可用的
Tree...
风格的集合。
- 避免使用
Vector
,除非需要利用其同步功能。
- 直到(除非)性能出现问题,否则不用担心最优化。
集合是 Java 语言的最强大的一个方面。不要害怕使用集合,但要提防“转向”。例如,以下是一个从 Array
转换到 ArrayList
的一个便利方法:
Adult adult1 = new Adult();
Adult adult2 = new Adult();
Adult adult3 = new Adult();
List immutableList = Arrays.asList(new Object[] { adult1, adult2, adult3 });
theList.add(new Adult());
这个代码抛出一个 UnsupportedOperationException
,因为由 Arrays.asList()
返回的 List
是不可变的。而您又无法将新的元素添加到不可变的 List
中,所以必须留心一点。
posted on 2005-11-30 12:00
Java&Inter 阅读(685)
评论(0) 编辑 收藏 所属分类:
Java技术