`
xifangyuhui
  • 浏览: 189049 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

TreeSet浅析

阅读更多

java.lang.Object
  |_ java.util.AbstractCollection<E>
    |_ java.util.AbstractSet<E>
        |_   java.util.TreeSet<E>
TreeSet类声明如下:
public class TreeSet<E>
  extends AbstractSet<E>
  implements SortedSet<E>, Cloneable, java.io.Serializable
因为实现了SortedSet类,所以具有自然排序的功能。
TreeSet和HashSet相同的地方,就是集合里面不允许有重复的元素。 自然排序情况下,一个TreeSet中只允许存放同一类型的多个元素,这里要求不是自定义的类。 例如:
Set treeSet = new TreeSet();
  treeSet.add(new String("aaa"));
  treeSet.add(new String("aaa"));
  treeSet.add(new String("bbb"));
  treeSet.add(new String("ccc"));
  treeSet.add(new String("aaa"));
  System.out.println(treeSet);
结果输出为:
[aaa, bbb, ccc]
这时,treeSet.size()=3。而且,它是经过排序的输出。
如果有多个类的对象都加入到TreeSet集合中,就会发生异常。 比如:
treeSet.add(new String("aaa"));
treeSet.add(new Integer(100));
System.out.println(treeSet);
发生异常:
Exception in thread "main" java.lang.ClassCastException: java.lang.String
at java.lang.Integer.compareTo(Integer.java:35)
at java.util.TreeMap.compare(TreeMap.java:1093)
at java.util.TreeMap.put(TreeMap.java:465)
at java.util.TreeSet.add(TreeSet.java:210)
at org.shirdrn.TreeSetTest.main(TreeSetTest.java:18)
而对于自定义的类,它的对象只能存放一个,而且实现类不需要实现Comparable接口。
但是,如果 想要存放多个自定义的类的对象,不实现Comparable接口就会发生java.lang.ClassCastException异常 。因此, 想要能够进行客户化排序,必须实现比较器
实现Comparable接口,就要实现 compareTo()方法 。而TreeSet 又不存储相同的元素,这就要求自定义的类重写hashCode()和equals()方法
class Person implements Comparable{
private String name;
private Integer age;
public Integer getAge() {
  return age;
}
public void setAge(Integer age) {
  this.age = age;
}
public String getName() {
  return name;
}
public void setName(String name) {
  this.name = name;
}

public boolean equals(Object o){
  if(this == o){
  return true;
  }
  if(! (o instanceof Person)){
  return false;
  }
  final Person other = (Person)o;
  if(this.name.equals(other.getName()) && this.age.equals(other.getAge())){
  return true;
  }
  else{
  return false;
  }
}

public int hashCode(){
  int result;
  result = (name == null?0:name.hashCode());
  result = 37*result + (age == null?0:age.hashCode());
  return result;
}
public int compareTo(Object o){
  Person other = (Person)o;
  if(this.name.compareTo(other.getName()) > 0){
  return 1;
  }
  if(this.name.compareTo(other.getName()) < 0){
  return -1;
  }
  if(this.getAge().intValue() > other.getAge().intValue()){
  return 1;
  }
  if(this.getAge().intValue() < other.getAge().intValue()){
  return -1;
  }
  return 0;
}

}
测试一下:
Set treeSet = new TreeSet();
  Person p1 = new Person();
  p1.setName("shirdrn");
  p1.setAge(new Integer(26));
  treeSet.add(p1);
  Person p2 = new Person();
  p2.setName("shirdrn");
  p2.setAge(new Integer(26));
  treeSet.add(p2);
  System.out.println(treeSet);
实例化了2个Person对象,实际上他们是同一个,因此只输出一个:
[org.shirdrn.Person@c29b5984]
如果将p2的name设置为p2.setName("Keller"),则输出两个:
[org.shirdrn.Person@5462263d, org.shirdrn.Person@c29b5984]
由于在Person类中实现类了compareTo()方法,输出结果是排序的,首先按照name排序,然后再按照age排序:
while(it.hasNext()){
  Person p = (Person)it.next();
  System.out.println("name = "+p.getName()+" || age = "+p.getAge());
  }
输出结果为:
name = Keller || age = 26
name = shirdrn || age = 26
name按照字母序排序。如果name相同,就按照age数字序排序。
TreeSet具有一些和HashSet类似的方法。

TreeSet的主要性质

1、TreeSet中不能有重复的元素;

2、TreeSet具有排序功能;

3、TreeSet中的元素必须实现Comparable接口并重写compareTo()方法,TreeSet判断元素是否重复 、以及确定元素的顺序 靠的都是这个方法;(这条性质比较重要,如果读者对TreeSet内部机制比较熟悉的话这条性质应该不难理解;如果读者不太理解的话可以参看以下这篇文章http://wlh269.iteye.com/blog/376430 )

4、对于java类库中定义的类,TreeSet可以直接对其进行存储,如String,Integer等(因为这些类已经实现了Comparable接口);

5、对于自定义类,如果不做适当的处理,TreeSet中只能存储一个该类型的对象实例,请看程序示例:

import java.util.*;
public class TreeSetDemo{
 public static void main(String args[]){
  TreeSet<Demo> tSet=new TreeSet<Demo>();
  Demo d1=new Demo(1,"abc");
  Demo d2=new Demo(2,"xyz");
    
  tSet.add(d1);
  tSet.add(d2);//如果有这条语句,运行程序时会抛出ClassCastException异常
                       //如果没有这条语句,程序会正常运行,并输出d1的内容
  Iterator itr=tSet.iterator();
  while(itr.hasNext()){
   Demo d=(Demo)itr.next();
   System.out.print(d.a+" "+d.b);
   System.out.println();
  }
 } 
}
class Demo{
 int a;
 String b;
 public Demo(int a,String b){
  this.a=a;
  this.b=b;
 }
}

在TreeSet中存储自定义的类的实现方法

示例:

import java.util.*;
public class TreeSetDemo{
 public static void main(String args[]){
  TreeSet<Demo> tSet=new TreeSet<Demo>();
  Demo d2=new Demo(2,"xyz");
  Demo d3=new Demo(2,"uvw");

  Demo d1=new Demo(1,"abc");
  
  tSet.add(d1);
  tSet.add(d2);
  tSet.add(d3);


  Iterator itr=tSet.iterator();
  while(itr.hasNext()){
   Demo d=(Demo)itr.next();
   System.out.print(d.a+" "+d.b);//注意此程序运行时会输出几个元素
   System.out.println();
  }
 } 
}
class Demo implements Comparable{
 int a;
 String b;
 public Demo(int a,String b){
  this.a=a;
  this.b=b;
 }
  public int compareTo(Object o){
   Demo demo=(Demo)o;
  if(this.a>demo.a){
   return 1;
  }else if(this.a<demo.a){
   return -1;
  }else{
   return 0;
  }
 }
}

解析: 上面程序会输出两个元素,并且是以a为判断标准按序输出的。当调用TreeSet的add()方法时,在TreeSet的内部会间接调用Demo的compareTo()方法、然后和TreeSet中已经存在的其他元素一一进行比较,在比较的过程中完成“判断是否重复”以及“排序”的功能:当在某次比较的过程中发现compareTo()返回0,就会认为待加入的元素已经存在于TreeSet中,返回-1或1的话就会根据TreeSet默认的比较器进行排序。

下面对程序进行修改,重写compareTo()方法,让TreeSet以a和b两个属性为依据来判断元素是否重复以及元素的顺序,请看下面的示例:

import java.util.*;
public class TreeSetDemo{
 public static void main(String args[]){
  TreeSet<Demo> tSet=new TreeSet<Demo>();
  Demo d1=new Demo(1,"abc");
  Demo d2=new Demo(2,"xyz");
  Demo d3=new Demo(2,"uvw");
  
  tSet.add(d1);
  tSet.add(d2);
  tSet.add(d3);
  
  Iterator itr=tSet.iterator();
  while(itr.hasNext()){
   Demo d=(Demo)itr.next();
   System.out.print(d.a+" "+d.b);//注意这次输出的元素个数
   System.out.println();
  }
 } 
}
class Demo implements Comparable{
 int a;
 String b;
 public Demo(int a,String b){
  this.a=a;
  this.b=b;
 }
  public int compareTo(Object o){
   Demo demo=(Demo)o;
   if(this.a==demo.a&&this.b.equals(demo.b)){
   return 0;
  }else if(this.a>demo.a){
   return 1;
  }else {
   return -1;
  }
 }
}

解析 :这次改动了compareTo()方法,程序输出了三个元素d1,d2和d3;当我们自己定义类,并且需要将自定义的类存到TreeSet中的时候,需要认真考虑compareTo的定义方式即需要认真考虑实际应用中依据什么判断元素是否重复和元素的顺序。

本文转自:http://blog.csdn.net/lubiaopan/archive/2009/11/10/4795411.aspx

分享到:
评论

相关推荐

    TreeSet 红黑树结构算法

    TreeSet 红黑树结构算法 TreeSet 红黑树结构算法是 Java 中的一种数据结构,它是基于红黑树数据结构的实现。红黑树是一种自平衡的排序二叉树,它可以保证快速检索指定节点。TreeSet 和 TreeMap 之间存在着紧密的...

    java 集合框架(TreeSet练习)

    在Java集合框架中,`TreeSet`是一个有序、不可重复的集合,它基于红黑树(Red-Black Tree)数据结构实现。`TreeSet`在许多场景下比其他集合如`ArrayList`或`HashSet`更有优势,因为它的元素总是按特定顺序排列,并且...

    java泛型 用了treeset

    使用TreeSet和Comparator,编写TreeSetTest2类,要求对TreeSet中的元素1-元素10进行排列,排序逻辑为奇数在前偶数在后,奇数按照升序排列,偶数按照降序排列。 如果需要的话可以下载,有写成文章的。有写了一点中文...

    HashSet和TreeSet_围墙之外

    HashSet和TreeSet是Java集合框架中的两种重要数据结构,它们都是Set接口的实现类,用于存储不重复的元素。在编程实践中,理解它们的区别和应用场景至关重要。 HashSet是基于HashMap实现的,它不保证元素的顺序,...

    javaTreeSet实现图书管理系统

    在Java编程语言中,`TreeSet` 是一种集合框架下的数据结构,它实现了SortedSet接口,提供了有序且无重复元素的存储。在这个“javaTreeSet实现图书管理系统”中,我们可以利用`TreeSet`的特性来构建高效且功能完备的...

    TreeSet集合用法

    介绍TreeSet集合用法,向TreeSet集合中添加类的对象,此类需实现Comparable接口,有实例,供需要的朋友下载学习。

    用java的TreeSet写的一个求并集算法

    在Java编程中,集合框架是处理数据的重要工具,而`TreeSet`作为其中之一,它是一个有序、不包含重复元素的集合。本知识点主要探讨如何利用Java的`TreeSet`类来实现两个集合的并集算法。 `TreeSet`是基于红黑树(Red...

    treeset 和 hashlist 实现的扑克牌游戏

    本话题将重点关注`TreeSet`和`ArrayList`(而非`hashlist`,可能是`ArrayList`的误写)这两种数据结构在实现扑克牌游戏中的应用。我们将深入探讨它们各自的特点以及在特定场景下的选择。 首先,让我们了解`...

    学生成绩排序(TreeSet方式实现)

    `TreeSet`是Java集合框架中的一个类,它继承自`AbstractSet`并实现了`NavigableSet`接口。`TreeSet`的主要特点就是它会自动按照一定的顺序对存储的元素进行排序。在这个场景下,我们使用`TreeSet`来实现学生成绩的...

    treemap treeset hashset hashmap 简要介绍

    在Java编程语言中,集合框架提供了多种数据结构来存储和操作数据,其中`TreeMap`、`TreeSet`、`HashSet`以及`HashMap`是最常用的数据结构之一。这些集合类各自有着独特的特性和应用场景,下面将对它们进行详细介绍。...

    排序之HashSet和TreeSet的区别

    在Java编程语言中,集合框架是处理数据的重要组成部分,其中`HashSet`和`TreeSet`是两种常用的Set接口实现类。它们各自具有独特的特性和用途,理解它们的区别对于编写高效且正确的代码至关重要。 首先,`HashSet`是...

    (TreeSet) s.subSet(608, true, 611, true)

    标题中的"(TreeSet) s.subSet(608, true, 611, true)"是一个Java编程中关于TreeSet集合的操作。TreeSet是Java集合框架中的一种有序、可重复的元素集合,它实现了SortedSet接口,内部基于红黑树(Red-Black Tree)...

    java集合-TreeSet的使用

    TreeSet 是 Java 中的一个集合类,它实现了 SortedSet 接口,并且使用红黑树作为底层数据结构。TreeSet 具有以下主要特点: 排序性:TreeSet 中的元素是有序的,默认按照元素的自然顺序进行排序。或者,可以在创建 ...

    Java SE程序 TreeSet类中自定义CompareTo类

    Java SE程序 TreeSet类中自定义CompareTo类Java SE程序 TreeSet类中自定义CompareTo类Java SE程序 TreeSet类中自定义CompareTo类Java SE程序 TreeSet类中自定义CompareTo类Java SE程序 TreeSet类中自定义CompareTo类...

    Java数据结构--13.Java8数据结构TreeSet.pdf

    《Java8数据结构——TreeSet详解》 在Java集合框架中,TreeSet是一个重要的数据结构,它是Set接口的实现类之一,与HashSet和LinkedHashSet不同,TreeSet具有排序功能,这是因为其不仅继承自AbstractSet,还实现了...

    TreeSet 不用自然排序自己做比较器

    public int compare(String o1,String o2) { return o1.length()-o2.length();... TreeSet ts = new TreeSet(com); ts.add("string"); ts.add("char"); ts.add("nothing�"); System.out.println(ts);

    HashSet和TreeSet.doc

    HashSet 和 TreeSet 是 Java 中两种常用的 Set 集合实现,它们都继承自 Set 接口,但实现方式和特性上存在显著差异。 首先,HashSet 是基于哈希表(HashMap 实例)来存储元素的,因此它提供了快速的插入、删除和...

    在TreeSet中添加自定义对象

    ### 在TreeSet中添加自定义对象 #### 一、前言 在Java编程语言中,`TreeSet`是一个实现了`Set`接口的类,它基于红黑树(Red-Black tree)实现,能够保证集合中的元素是有序的,并且不允许重复的元素。`TreeSet`有两...

    用TreeSet,添加字符串,按照长度和字母顺序排序

    用TreeSet添加字符串,按照字符串首字母字母顺序和字符串长度顺序排序

    TreeSet判断重复元素解析及代码示例

    其中,`TreeSet`是Set接口的一个实现,它内部使用了`TreeMap`的数据结构。`TreeSet`保证了其元素按照自然顺序或者自定义比较器的顺序进行排序。在`TreeSet`中,元素的唯一性是由`compareTo()`方法决定的,而不是`...

Global site tag (gtag.js) - Google Analytics