学习笔记之JavaSE(33)--JavaAPI详解8
2016-11-23 21:08
337 查看
今天学习的内容是集合类之TreeSet
TreeSet的底层数据结构是二叉树,是不同步的。与HashSet不同,TreeSet是有序的,准确来说TreeSet可以按照指定规则对元素进行排序。注意由于TreeSet中的元素要按照制定规则进行排序,所以TreeSet不能存储null。
那么TreeSet是如何进行排序的呢?有两种方法:
自然排序:元素所属的类实现Comparable接口,并实现其compareTo()方法,排序规则即为compareTo()方法的内容。在存储元素时,TreeSet会调用该元素的compareTo()方法与集中其它元素进行比较,如果该元素小于、等于或大于指定元素,则分别返回负整数、零或正整数,如果返回零即认为两元素重复,不会存储该元素,如果返回负整数或正整数则会将该元素存储在与之比较的元素的前面或后面。JavaAPI中大部分类都实现了Comparable接口并实现了其compareTo()方法,比如包装类和String类
比较器排序:定义一个实现了Comparator接口的比较器,并实现其compare()方法,排序规则即为compare()方法的内容,最后将其实例作为TreeSet构造函数的参数传入集中。在存储元素时,TreeSet会调用比较器的compare()方法将该元素与集中其它元素进行比较,比较结果与排序原则同上。如果某元素所属的类不具备自然排序,或者不想使用该类的自然排序,就可以使用比较器排序(实际开发中这种情况比较多见,所以比较器排序比较常用),注意比较器排序的优先级高于自然排序
PS:如果想让元素添加顺序排序也很简单,令compareTo()方法或compare()方法的返回值恒为正整数即可。
关于TreeSet两种比较方式的示例程序:
实际开发中很有可能不想使用某类的自然排序,但又无法修改该类,这时候就可以使用比较器排序,由于比较器排序的优先级要高于自然排序,所以排序规则使用的是compare()方法中的内容,如下例:
总结:如果要按照特定规则对元素进行排序,建议使用TreeSet;如果想让元素按照添加顺序排序,建议使用LinkedHashSet;其他情况都使用HashSet
TreeSet的底层数据结构是二叉树,是不同步的。与HashSet不同,TreeSet是有序的,准确来说TreeSet可以按照指定规则对元素进行排序。注意由于TreeSet中的元素要按照制定规则进行排序,所以TreeSet不能存储null。
那么TreeSet是如何进行排序的呢?有两种方法:
自然排序:元素所属的类实现Comparable接口,并实现其compareTo()方法,排序规则即为compareTo()方法的内容。在存储元素时,TreeSet会调用该元素的compareTo()方法与集中其它元素进行比较,如果该元素小于、等于或大于指定元素,则分别返回负整数、零或正整数,如果返回零即认为两元素重复,不会存储该元素,如果返回负整数或正整数则会将该元素存储在与之比较的元素的前面或后面。JavaAPI中大部分类都实现了Comparable接口并实现了其compareTo()方法,比如包装类和String类
比较器排序:定义一个实现了Comparator接口的比较器,并实现其compare()方法,排序规则即为compare()方法的内容,最后将其实例作为TreeSet构造函数的参数传入集中。在存储元素时,TreeSet会调用比较器的compare()方法将该元素与集中其它元素进行比较,比较结果与排序原则同上。如果某元素所属的类不具备自然排序,或者不想使用该类的自然排序,就可以使用比较器排序(实际开发中这种情况比较多见,所以比较器排序比较常用),注意比较器排序的优先级高于自然排序
PS:如果想让元素添加顺序排序也很简单,令compareTo()方法或compare()方法的返回值恒为正整数即可。
关于TreeSet两种比较方式的示例程序:
public class Test57 { public static void main(String[] args) { // 基本用法 TreeSet<String> set = new TreeSet<>(); set.add("b"); set.add("c"); set.add("a"); set.add("a"); System.out.println(set);// [a, b, c] String类本身就实现了Comparable接口的compareTo()方法 Iterator<String> it = set.iterator(); while (it.hasNext()) { String str = it.next(); System.out.println(str); } // 使用自然排序 TreeSet<Person> ts = new TreeSet<>(); ts.add(new Person("zhangsan", 21)); ts.add(new Person("lisi", 22));// 如果Person类没有实现Comparable接口,会发生ClassCastException ts.add(new Person("wangwua", 23)); ts.add(new Person("wangwub", 23)); ts.add(new Person("zhaoliu", 24)); System.out.println(ts);// [Person [name=zhangsan, age=21], Person // [name=lisi, age=22], Person [name=wangwua, // age=23], Person [name=wangwub, age=23], // Person [name=zhaoliu, age=24]] Iterator<Person> it_p = ts.iterator(); while (it_p.hasNext()) { Person p = it_p.next(); System.out.println(p);// 按照年龄进行从小到大排序,如果年龄相等,再按照姓名进行自然排序 } // 使用比较器排序 TreeSet<Person> ts_com = new TreeSet<>(new ComparatorByName()); ts_com.add(new Person("zhangsan", 21)); ts_com.add(new Person("lisi", 22)); ts_com.add(new Person("wangwu", 23)); ts_com.add(new Person("wangwu", 24)); ts_com.add(new Person("zhaoliu", 24)); System.out.println(ts_com);// [Person [name=lisi, age=22], Person // [name=wangwu, age=23], Person // [name=wangwu, age=24], Person // [name=zhangsan, age=21], Person // [name=zhaoliu, age=24]] Iterator<Person> it_com = ts_com.iterator(); while (it_com.hasNext()) { Person p = it_com.next(); System.out.println(p);// 按照姓名进行自然排序,如果姓名相同,再按照年龄大小进行排序 } } } class Person implements Comparable<Person> { private String name; private int age; public Person() { super(); } public Person(String name, int age) { super(); this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public String toString() { return "Person [name=" + name + ", age=" + age + "]"; } @Override public int hashCode() { // 覆盖Object的hashCode()方法 final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) {// 覆盖Object的equals()方法 if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Person other = (Person) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } // 本例中按照年龄进行从小到大排序,如果年龄相等,再按照姓名进行自然排序 @Override public int compareTo(Person o) { int temp = this.age - o.age; return temp == 0 ? this.name.compareTo(o.name) : temp; } } // 自定义比较器,按照姓名进行自然排序,如果姓名相同,再按照年龄大小进行排序 class ComparatorByName implements Comparator<Person> { @Override public int compare(Person o1, Person o2) { int temp = o1.getName().compareTo(o2.getName()); return temp == 0 ? o1.getAge() - o2.getAge() : temp; } }
实际开发中很有可能不想使用某类的自然排序,但又无法修改该类,这时候就可以使用比较器排序,由于比较器排序的优先级要高于自然排序,所以排序规则使用的是compare()方法中的内容,如下例:
public class Test58 { public static void main(String[] args) { TreeSet<String> ts = new TreeSet<>(new ComparatorByStringLength()); ts.add("abc"); ts.add("cba"); ts.add("zzqz"); ts.add("aaaqw"); ts.add("nba"); System.out.println(ts);// [abc, cba, nba, zzqz, aaaqw] } } // 按照字符串长度进行排序,如果长度相同,按照字符串的自然顺序进行排序 class ComparatorByStringLength implements Comparator<String> { @Override public int compare(String o1, String o2) { int temp = o1.length() - o2.length(); return temp == 0 ? o1.compareTo(o2) : temp; } }
总结:如果要按照特定规则对元素进行排序,建议使用TreeSet;如果想让元素按照添加顺序排序,建议使用LinkedHashSet;其他情况都使用HashSet
相关文章推荐
- 学习笔记之JavaSE(29)--JavaAPI详解4
- 学习笔记之JavaSE(28)--JavaAPI详解3
- 学习笔记之JavaSE(30)--JavaAPI详解5
- JavaMail(JAVA邮件服务) API详解
- JavaMail(JAVA邮件服务) API详解 (2)
- javadoc - Java API 文档生成器详解 转贴
- javaAPI File.separatorChar 方法详解
- 转 JavaMail(JAVA邮件服务) API详解 (1)
- 详解Java的JDBC API的存储过程与SQL转义语法的使用
- JavaMail(JAVA邮件服务) API详解 (2)
- JavaMail(JAVA邮件服务) API详解 (3)
- JavaMail(JAVA邮件服务) API详解 (4)
- Java规则引擎与其API应用详解 (转载于Java家)
- JavaMail(JAVA邮件服务) API详解 (4)
- JavaMail(JAVA邮件服务) API详解 (4)
- JavaMail(JAVA邮件服务) API详解 (3)
- 详解Java 规则引擎及其API
- javamail API 详解
- JavaMail(JAVA邮件服务) API详解
- JavaMail(JAVA邮件服务) API详解 (3)