开课吧Java课堂:如何使用比较函数?

127 阅读3分钟

下面是一个说明定制的比较函数能力的例子。该例子实现compare( )方法以便它按正常顺序的逆向进行操作。因此,它使得一个树集合按逆向的顺序进行存储。

// Use a custom comparator. 
import java.util.*; 
// A reverse comparator for strings. 
class MyComp implements Comparator { 
 public int compare(Object a, Object b) { 
 String aStr, bStr; 
 aStr = (String) a; 
 bStr = (String) b; 
 // reverse the comparison 
 return bStr.compareTo(aStr); 
 } 
 // no need to override equals 
} 
class CompDemo { 
 public static void main(String args[]) { 
 // Create a tree set 
 TreeSet ts = new TreeSet(new MyComp()); 
 // Add elements to the tree set 
 ts.add("C"); 
 ts.add("A"); 
 ts.add("B"); 
 ts.add("E"); 
 ts.add("F"); 
 ts.add("D"); 
 // Get an iterator 
 Iterator i = ts.iterator(); 
 // Display elements 
 while(i.hasNext()) { 
 Object element = i.next(); 
 System.out.print(element + " "); 
 } 
 System.out.println(); 
 } 
} 

正如下面的输出所示,树按照逆向顺序进行存储:

F E D C B A 

仔细观察实现Comparator并覆盖compare( )方法的MyComp类(正如前面所解释的那样,覆盖equals( )方法既不是必须的,也不是常用的)。

在compare( )方法内部,String方法compareTo( )比较两个字符串。然而由bStr——不是aStr——调用compareTo( )方法,这导致比较的结果被逆向。

对应一个更实际的例子,下面的例子是用TreeMap程序实现前面介绍的存储账目资产平衡表例子的程序。在前面介绍的程序中,账目是按名进行排序的,但程序是以按照名字进行排序开始的。下面的程序按姓对账目进行排序。为了实现这种功能,程序使用了比较函数来比较每一个账目下姓的排序。得到的映射是按姓进行排序的。

// Use a comparator to sort accounts by last name. 
import java.util.*; 
// Compare last whole words in two strings. 
class TComp implements Comparator { 
 public int compare(Object a, Object b) { 
 int i, j, k; 
 String aStr, bStr; 
 aStr = (String) a; 
 bStr = (String) b; 
 // find index of beginning of last name 
 i = aStr.lastIndexOf(' '); 
 j = bStr.lastIndexOf(' '); 
 k = aStr.substring(i).compareTo(bStr.substring(j)); 
 if(k==0) // last names match, check entire name 
 return aStr.compareTo(bStr); 
 else 
 return k; 
 } 
 // no need to override equals 
} 
class TreeMapDemo2 { 
 public static void main(String args[]) { 
 // Create a tree map 
 TreeMap tm = new TreeMap(new TComp()); 
 
 // Put elements to the map 
 tm.put("John Doe", new Double(3434.34)); 
 tm.put("Tom Smith", new Double(123.22)); 
 tm.put("Jane Baker", new Double(1378.00)); 
 tm.put("Todd Hall", new Double(99.22)); 
 tm.put("Ralph Smith", new Double(-19.08)); 
 // Get a set of the entries 
 Set set = tm.entrySet(); 
 // Get an iterator 
 Iterator itr = set.iterator(); 
 // Display elements 
 while(itr.hasNext()) { 
 Map.Entry me = (Map.Entry)itr.next(); 
 System.out.print(me.getKey() + ": "); 
 System.out.println(me.getValue()); 
 } 
 System.out.println(); 
 // Deposit 1000 into John Doe's account 
 double balance = ((Double)tm.get("John Doe")).doubleValue(); 
 tm.put("John Doe", new Double(balance + 1000)); 
 System.out.println("John Doe's new balance: " + 
 tm.get("John Doe")); 
 } 
} 

这里是程序的输出结果,注意此时的账目是按姓进行排序的:

Jane Baker: 1378.0 
John Doe: 3434.34 
Todd Hall: 99.22 
Ralph Smith: -19.08 
Tom Smith: 123.22 
John Doe’s new balance: 4434.34 

比较函数类TComp比较两个包含姓和名的字符串。它首先比较姓。具体是这样做的,它首先寻找每一个字符串中最后一个空格的下标,然后比较从这个位置开始的每一个元素的子字符串。当两个字符串中姓完全相等时,它再比较两个名。这样就形成了一个先按姓进行排序,在姓相同的情况下,再按名字进行排序的树型映射。通过程序的输出中Ralph Smith出现在Tom Smith之前的结果可以看到这一点。