有的时候我们需要将自己定义的对象,有序输出。因为一般我们程序的中间结果需要存储在容器里,那么怎样对容器中的对象按照一定次序输出就是程序员经常需要考虑的问题。本片文章探讨了怎样有序化输出容器中的对象的问题。涉及的库包括Guava和JDK API.
- 使用TreeMap 或者TreeSet按照一定次序来存储对象
㈠ TreeSet是通过TreeMap实现的。
原生java库已经提供两个容器TreeMap、TreeSet。但是因为这两个集合类有这密切的关系。将TreeMap的键值设置为NULL,那么TreeMap就变成了TreeSet。看看jdk api文档中关于TreeSet一节,第一句就是A implementation based on a 。这句话意思是一个的实现类都是基于TreeMap,而TreeSet实现了,从这儿可以发现二者之间的密切关系了吧.
㈡ 对存入对象的要求
下面的这段话来自于TreeMap的API文档中。
Note that the ordering maintained by a tree map, like any sorted map, and whether or not an explicit comparator is provided, must be consistent with equals
if this sorted map is to correctly implement the Map
interface. (See Comparable
or Comparator
for a precise definition of consistent with equals.) This is so because the Map
interface is defined in terms of the equals
operation, but a sorted map performs all key comparisons using its compareTo
(or compare
) method, so two keys that are deemed equal by this method are, from the standpoint of the sorted map, equal. The behavior of a sorted map is well-defined even if its ordering is inconsistent with equals
; it just fails to obey the general contract of the Map
interface.
说明一个类存入TreeSet和TreeMap的时候,是调用Comparator来比较是否存入的键与已经存在的键冲突的。
因此,将一个对象存入TreeSet和TreeMap的时候,一定要传入一个Comparator方法。同时注意一定要用Comparator来严格区分每一个元素。
1 import java.util.Set; 2 import java.util.TreeSet; 3 class Person implements Comparable{ 4 private String name; 5 private int age; 6 7 //构造器 8 public Person() { 9 }10 11 public Person(String name, int age) {12 this.setAge(age);13 this.setName(name);14 }15 16 public int getAge() {17 return age;18 }19 20 public void setAge(int age) {21 this.age = age;22 }23 24 public String getName() {25 return name;26 }27 28 public void setName(String name) {29 this.name = name;30 }31 32 @Override33 public int compareTo(Person o) {34 int i = new Integer(o.getAge()).compareTo(new Integer(this.getAge()));35 if (i != 0) {36 return i;37 }38 return this.getName().compareTo(o.getName());39 }40 }41 42 public class Test {43 public static void main(String[] args) {44 Set set = new TreeSet();45 set.add(new Person("十八子", 24));46 set.add(new Person("十八子", 25));47 set.add(new Person("大连", 20));48 set.add(new Person("北京", 20));49 set.add(new Person("北京", 33));50 set.add(new Person("北京", 26));51 52 for (Person person : set) {53 System.out.println(String.format("名字是:%s,年龄是:%d",54 person.getName(), person.getAge()));55 }56 }57 58 }
输出结果:
1 名字是:北京,年龄是:332 名字是:北京,年龄是:263 名字是:十八子,年龄是:254 名字是:十八子,年龄是:245 名字是:北京,年龄是:206 名字是:大连,年龄是:20
本程序是让类直接实现Comparable接口。也可以在新建Set对象的时候,传入一个比较器。参考下面的代码。输出结果同上,不再贴出。
1 import java.util.Comparator; 2 import java.util.Set; 3 import java.util.TreeSet; 4 class Person { 5 private String name; 6 private int age; 7 8 //构造器 9 public Person() {10 }11 12 public Person(String name, int age) {13 this.setAge(age);14 this.setName(name);15 }16 17 public int getAge() {18 return age;19 }20 21 public void setAge(int age) {22 this.age = age;23 }24 25 public String getName() {26 return name;27 }28 29 public void setName(String name) {30 this.name = name;31 }32 33 }34 35 public class Test {36 public static void main(String[] args) {37 Setset = new TreeSet(new Comparator () {38 @Override39 public int compare(Person o1, Person o2) {40 int i = new Integer(o2.getAge()).compareTo(new Integer(o1.getAge()));41 if (i != 0) {42 return i;43 }44 return o1.getName().compareTo(o2.getName());45 }46 });47 set.add(new Person("十八子", 24));48 set.add(new Person("十八子", 25));49 set.add(new Person("大连", 20));50 set.add(new Person("北京", 20));51 set.add(new Person("北京", 33));52 set.add(new Person("北京", 26));53 54 for (Person person : set) {55 System.out.println(String.format("名字是:%s,年龄是:%d",56 person.getName(), person.getAge()));57 }58 }59 60 }61 62