合肥专业网站制作团队,北京大学网络服务,品牌宣传方案怎么写,网站开发 成都一、TreeSet 概述 1、TreeSet是 SortedSet 接口的实现类#xff0c; TreeSet 可以确保集合元素处于排序状态。 2、TreeSet顾名思义他内部维护的是一个TreeMap#xff0c;底层是红黑二叉树#xff0c;他使得集合内都是有序的序列。 3、Tree可以按照添加对象的指定属性…
一、TreeSet 概述 1、TreeSet是 SortedSet 接口的实现类 TreeSet 可以确保集合元素处于排序状态。 2、TreeSet顾名思义他内部维护的是一个TreeMap底层是红黑二叉树他使得集合内都是有序的序列。 3、Tree可以按照添加对象的指定属性进行排序所以向TreeSet中添加的数据要求是相同类的对象。 4、两种排序方式自然排序实现Comparable接口 和 定制排序Comparator 5、自然排序中比较两个对象是否相同的标准为compareTo()返回0.不再是equals() 6、定制排序中比较两个对象是否相同的标准为compare()返回0.不再是equals() 7、对 TreeSet进行遍历的时候默认是使用自然排序的规则来排序的 8、TreeSet 添加自定义类的对象时候必须要有自然排序或定制排序否则抛出异常cannot cast to java.lang.Comparable;
二、TreeSet 结构
1、TreeSet 声明
1 public class TreeSetE extends AbstractSetE
2 implements NavigableSetE, Cloneable, java.io.Serializable
2、TreeSet 类继承结构 3、红黑树
TreeSet和后要的TreeMap采用红黑树的存储结构
特点有序查询速度比List快
三、TreeSet 创建
1、构造器
TreeSet是基于红黑树结构实现的会对元素进行排序TreeSet 提供了五种构造器
public TreeSet() {this(new TreeMapE,Object());
}TreeSet(NavigableMapE,Object m) {this.m m;
}
public TreeSet(Comparator? super E comparator) {this(new TreeMap(comparator));
}
public TreeSet(Collection? extends E c) {this();addAll(c);
}
public TreeSet(SortedSetE s) {this(s.comparator());addAll(s);
}里面的 m 属性是什么 /*** The backing map.*/private transient NavigableMapE,Object m;// Dummy value to associate with an Object in the backing Mapprivate static final Object PRESENT new Object();//加入Java开发交流君样593142328一起吹水聊天可以看到里面是维护了一个 NavigableMap。
2、通过 Comparator 实例创建 TreeSet
上面的四个构造函数中着重要介绍第三个它通过Comparator实例来创建TreeMap那么Comparator到底是何方神圣呢
通过阅读Comparator的源码发现这是一个用于集合类排序的辅助接口用户需要实现compare方法。
如果用户用了这种方式创建TreeSet那么集合元素就不需要做额外处理否则集合元素都需要实现Comparable接口因为Tree在排序的时候会调用compare或者compareTo方法介绍TreeMap的时候会具体讲解。
下面来看看写的一个样例代码 public class MyComparator implements ComparatorPerson {Overridepublic int compare(Person o1, Person o2) {return o1.age - o2.age;}}
public class Person {public Integer age;public Person(Integer value) {this.age value;}
}
public static void TreeSetTest() {// TreeMap在底层put元素的时候会判断是否存在Comparator实例如果存在则每次添加元素排序比较的时候会调用compare接口。TreeSetPerson set new TreeSetPerson(new MyComparator());Person p1 new Person(1);Person p2 new Person(1);Person p3 new Person(5);Person p4 new Person(9);Person p5 new Person(10);set.add(p1);set.add(p2);set.add(p3);set.add(p4);set.add(p5);IteratorPerson i set.iterator();while (i.hasNext()) {Person p (Person) i.next();System.out.println(p.age);}
}
打印结果
1
5
9
10四、TreeSet 方法 五、NavigableSet接口介绍
常用方法
// 返回比当前元素小的最近的一个元素
public E lower(E e) {return m.lowerKey(e);
}
// 返回小于等于当前元素的最近一个元素
public E floor(E e) {return m.floorKey(e);
}
// 返回大于等于当前元素的最近一个元素
public E ceiling(E e) {return m.ceilingKey(e);
}
// 返回大于当前元素的最近一个元素
public E higher(E e) {return m.higherKey(e);
}六、TreeSet 与 比较器
1、自然排序 1自然排序TreeSet会调用集合元素的 compareTo(Object obj) 方法来比较元素之间的大小关系然后将集合元素按升序(默认情况)排列。 2如果试图把一个对象添加到TreeSet时则该对象的类必须实现 Comparable接口。 实现Comparable 的类必须实现compareTo(Object obj)方法两个对象即通过compareTo(Object obj)方法的返回值来比较大小。 3Comparable 的典型实现 ① BigDecimal、BigInteger 以及所有的数值型对应的包装类按它们对应的数值大小进行比较 ② Character按字符的 unicode值来进行比较 ③ Booleantrue 对应的包装类实例大于 false 对应的包装类实例 ④String按字符串中字符的 unicode 值进行比较 ⑤ Date、Time后边的时间、日期比前面的时间、日期大 4向 TreeSet 中添加元素时只有第一个元素无须比较compareTo()方法后面添加的所有元素都会调用compareTo()方法进行比较。 5因为只有相同类的两个实例才会比较大小所以向 TreeSet 中添加的应该是同一个类的对象。 6对于 TreeSet 集合而言它判断两个对象是否相等的唯一标准是两个对象通过 compareTo(Object obj)方法比较返回值。 7当需要把一个对象放入 TreeSet中重写该对象对应的 equals()方法时应保证该方法与 compareTo(Object obj) 方法有一致的结果如果两个对象通过 equals() 方法比较返回 true则通过 compareTo(Object obj)方法比较应返回 0。否则让人难以理解。
2、定制排序 1TreeSet的自然排序要求元素所属的类实现Comparable接口如果元素所属的类没有实现Comparable接口或不希望按照升序(默认情况)的方式排列元素或希望按照其它属性大小进行排序则考虑使用定制排序。定制排序通过Comparator接口来实现。需要重写compare(T o1,T o2)方法。 2利用int compare(T o1,T o2)方法比较o1和o2的大小如果方法返回正整数则表示o1大于o2如果返回0表示相等返回负整数表示o1小于o2 3要实现定制排序需要将实现Comparator接口的实例作为形参传递给TreeSet的构造器。 4此时仍然只能向TreeSet中添加类型相同的对象。否则发生ClassCastException异常。 5使用定制排序判断两个元素相等的标准是通过Comparator比较两个元素返回了0。 七、案例
1、自定义类的自然排序
案例
public class User implements Comparable{private String name;private int age;public User() {}public User(String name, int age) {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;}Overridepublic String toString() {return User{ name name \ , age age };}Overridepublic boolean equals(Object o) {System.out.println(User equals()....);if (this o) return true;if (o null || getClass() ! o.getClass()) return false;User user (User) o;if (age ! user.age) return false;return name ! null ? name.equals(user.name) : user.name null;}Overridepublic int hashCode() { //return name.hashCode() age;int result name ! null ? name.hashCode() : 0;result 31 * result age;return result;}//按照姓名从大到小排列,年龄从小到大排列Overridepublic int compareTo(Object o) {if(o instanceof User){User user (User)o;
// return -this.name.compareTo(user.name);int compare -this.name.compareTo(user.name);if(compare ! 0){return compare;}else{return Integer.compare(this.age,user.age);}}else{throw new RuntimeException(输入的类型不匹配);}}
}使用TreeSet保存
Testpublic void test1(){TreeSet set new TreeSet();set.add(new User(Tom,12));set.add(new User(Jerry,32));set.add(new User(Jim,2));set.add(new User(Mike,65));set.add(new User(Jack,33));set.add(new User(Jack,56));Iterator iterator set.iterator();while(iterator.hasNext()){System.out.println(iterator.next());}}注意如果在自然比较器中并没有对年龄进行比较当姓名一样时就会认为这两个对象一样不会再次存放
如果在比较器中对两个属性都进行了比较当有一个属性不一样就会放入 TreeSet中。
可以发现这里对两个对象的比较并不是使用 equals() 方法而是使用比较器来进行比较的。
2、自定义类的定制排序
定制排序
Testpublic void test2(){Comparator com new Comparator() {//按照年龄从小到大排列Overridepublic int compare(Object o1, Object o2) {if(o1 instanceof User o2 instanceof User){User u1 (User)o1;User u2 (User)o2;return Integer.compare(u1.getAge(),u2.getAge());}else{throw new RuntimeException(输入的数据类型不匹配);}}};TreeSet set new TreeSet(com); //按照给定的比较器进行排序set.add(new User(Tom,12));set.add(new User(Jerry,32));set.add(new User(Jim,2));set.add(new User(Mike,65));set.add(new User(Mary,33));set.add(new User(Jack,33));set.add(new User(Jack,56));Iterator iterator set.iterator();while(iterator.hasNext()){System.out.println(iterator.next());}}最后祝大家早日学有所成拿到满意offer