在看《java核心技术卷I》的时候再TreeSet的章节,看到了使用匿名内部类的实例,好奇后查了下相关信息,有两个博客写的很好,以后还需细看
先说下TreeSet的Test, TreeSet和Hashset的区别主要是前者是一个有序集合,使用的排序方法时红黑树的方法(类似于平衡二叉树AVL,详见算法导论)。在TreeSet中加入java中已定义的类时,如string,则加入时会自动调用其已经实现的comparable接口中的compareTo方法(按字母的字典序排列)对字符串进行排序。
但是如果要插入自定义的对象,就必须在对应的类中扩展comparable借口,并且实现其中的compareTo方法。 还有一个方法就是构造一个带有比较器(Comparator)的树。两种比较方法见下面的代码:
/* * 这个例子主要是练习comparable接口的comepleTo虚拟方法(单参数)和comparator接口的compare虚拟方法(两个参数)在进行对象比较的时候的差别 * 此外,TreeSet是一个排序树,按照红黑树的方法进行元素排序(红黑树类似于AVL树) */ import java.util.Comparator; import java.util.SortedSet; import java.util.TreeSet; public class TreeSetTest { @SuppressWarnings("unchecked") public static void main(String[] args) { SortedSet<Item> parts = new TreeSet<Item>(); TreeSet<Item> parts2 = new TreeSet<Item>(); /* * part.add的排序是Item类中通过扩展comparable接口后实现其compareTo的虚拟方法 */ parts.add(new Item("awhu", 345678123)); parts.add(new Item("pku", 234)); parts.add(new Item("duku", 123345)); parts.add(new Item("shagnhai", 4567)); //System.out.println(parts.toString()); System.out.println(parts); //两者写法一样效果,前者显示定义了对象实例输出的格式\ parts2.addAll(parts); System.out.println(parts.size()); SortedSet<Item> sortByDescription = new TreeSet<Item>( new Comparator<Item>() { public int compare(Item a, Item b) { String descrA = a.getDescription(); String descrB = b.getDescription(); return descrA.compareTo(descrB); //调用string类自身的compareTo方法 } }); /* * sortByDescription.addALL的排序是通过上面定义的带有比较器的树 中的比较规则来实现的 */ sortByDescription.addAll(parts); System.out.println(sortByDescription); /* * 上一步中用java匿名内部类定义的带有比较器comparator的树可以使用下面结构更为清晰,代码可读性更强的书写代替 */ ItemComparator comp = new ItemComparator(); SortedSet<Item> SortByDescription2 = new TreeSet<Item>(comp); SortByDescription2.addAll(parts); System.out.println(SortByDescription2); } } class Item implements Comparable<Item>{ private String description; private int partnumber; public Item(String aDescription, int aPartNumber) { description = aDescription; partnumber = aPartNumber; } public String getDescription() { return description; } public String toString() { return "[desciption=" + description + ",partnumber=" + partnumber + "]"; } public boolean equals(Object otherobject) { if(this == otherobject) return true; if(otherobject == null) return false; if(getClass()!= otherobject.getClass()) return false; Item other = (Item)otherobject; return description.equals(other.description) && partnumber == other.partnumber; } public int hashCode() { return 13*description.hashCode() + 17*partnumber; } public int compareTo(Item other) //必须要实现的一个方法 { return partnumber - other.partnumber; } } /*前面用java匿名内部类实现的带有比较器的树可以先定义一个扩展了比较器comparator接口并且实现了其中的compare虚拟方法的类ItemCompare, * 然后对该类ItemCompare实例化一个对象com,将这个对象作为TreeSet的构造函数中的 参数(函数对象):SortedSet<Item> SortByDescription2 = new TreeSet<Item>(comp); * * */ class ItemComparator implements Comparator<Item> { public int compare(Item a, Item b) { String descrA = a.getDescription(); String descrB = b.getDescription(); return descrA.compareTo(descrB); } }
其中在定义带有比较器(comparator)时就使用了匿名内部类。匿名内部类就是在外部类的实例就是在外部类中作为一个函数对象,没有必要特意为之申请一个变量,使其指向匿名内部类实例的对象。代码更为简洁,但是可读性降低。
带有比较器(comparator)的树的定义可以采用更为清晰的结构书写,在代码中已有提及。