`

TreeSet深入学习

    博客分类:
  • java
 
阅读更多
  /*
* TreeSet存储对象的时候, 可以排序, 但是需要指定排序的算法
*
* Integer能排序(有默认顺序), String能排序(有默认顺序), 自定义的类存储的时候出现异常(没有顺序)
*/
如果想把自定义类的对象存入TreeSet进行排序, 那么必须让类实现Comparable接口或者让集合自身具备比较性二种方法
TreeSet集合排序有两种方式,Comparable和Comparator区别:
1:让元素自身具备比较性,需要元素对象实现Comparable接口,覆盖compareTo方法。
2:让集合自身具备比较性,需要定义一个实现了Comparator接口的比较器,并覆盖compare方法,并将该类对象作为实际参数传递给TreeSet集合的构造函数。
第二种方式较为灵活。



与HashSet完全类似,TreeSet里面绝大部分方法都市直接调用TreeMap方法来实现的。

相同点:

    TreeMap和TreeSet都是有序的集合,也就是说他们存储的值都是拍好序的。
    TreeMap和TreeSet都是非同步集合,因此他们不能在多线程之间共享,不过可以使用方法Collections.synchroinzedMap()来实现同步
    运行速度都要比Hash集合慢,他们内部对元素的操作时间复杂度为O(logN),而HashMap/HashSet则为O(1)。

不同点:

    最主要的区别就是TreeSet和TreeMap非别实现Set和Map接口
    TreeSet只存储一个对象,而TreeMap存储两个对象Key和Value(仅仅key对象有序)
    TreeSet中不能有重复对象,而TreeMap中可以存在




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://xifangyuhui.iteye.com/blog/833979
分享到:
评论
发表评论

文章已被作者锁定,不允许评论。

相关推荐

    java 集合框架(TreeSet练习)

    Java集合框架是Java编程语言中一个非常重要的组成部分,它提供了数据结构和算法的实现,使得在处理各种数据存储和操作时更加便捷高效。...通过深入学习和实践,开发者可以更好地解决涉及排序和去重的问题。

    java深入学习笔记.pdf

    "java深入学习笔记.pdf" java是一种广泛应用的编程语言,具有平台独立性、对象oriented、分布式处理等特点。在java深入学习笔记.pdf中,我们可以学习到以下知识点: 一、java基础知识 * 变量声明:在java中,变量...

    【IT十八掌徐培成】Java基础第12天-02.TreeSet实现与Comparable接口.zip

    在Java编程语言中,`TreeSet`是一个基于`TreeMap`实现的有序集合。它遵循了`SortedSet`接口,因此元素在集合中是按照特定的...在学习和使用过程中,我们需要深入理解它们的工作原理,以便在实际项目中得心应手地应用。

    JCF(List、Set、Map)学习,实现了<key,value>按value排序噢

    标题中提到的“JCF(List、Set、Map)学习,实现了,value&gt;按value排序”是一个关键点,我们将深入探讨这个话题。 首先,让我们了解List、Set和Map的区别。List是有序的集合,允许重复元素,并且可以保持插入顺序;Set...

    Java深入学习

    "Java深入学习"的主题涵盖了从基础到高级的各种Java技术,包括语法、类库、框架以及最佳实践。下面将对Java的一些核心概念和重要知识点进行详细介绍。 1. **Java语法基础**:Java的语法基于C++,但更为简洁。它包括...

    深入学习java源码-Java-Collection-Framework:java集合框架详解,这里有集合框架的深入学习并且贴出了部分重要

    在深入学习Java源码时,理解并掌握Java集合框架至关重要。这个框架包括接口、类和算法,它们使得数据结构如数组、链表、队列、栈等的使用变得简单而高效。 首先,我们来看一下集合框架的基础接口。`Collection`是...

    java集合使用实例

    Java集合框架是Java编程语言中一个非常重要的组成部分,它提供了数据结构和算法的实现,使得在处理各种数据存储和操作时更加高效。...通过实践提供的实例,我们可以深入学习这些集合类的使用,并在具体项目中灵活应用。

    corejava学习(集合)

    通过深入学习集合框架,开发者可以更好地理解和利用Java的内存管理机制,提高代码的性能和可维护性。 首先,我们来探讨List接口,它代表一个有序的元素列表,允许重复元素。ArrayList和LinkedList是List接口的主要...

    java集合、常用类和String[参照].pdf

    在Java编程语言中,集合框架是处理对象组的重要工具,提供了灵活的数据存储和操作机制。在给定的文件中,我们重点关注的是Java集合框架、常用类...通过深入学习和实践,我们可以更好地利用这些工具来满足各种软件需求。

    Java学习笔记整理

    Java是世界上最流行的编程语言之...通过对这些笔记的深入学习,你可以掌握Java编程的核心概念,为实际开发打下坚实基础。记住,理论知识与实践结合是提高编程技能的关键,所以尝试在理解这些概念后编写代码来实践它们。

    java _Tree.rar

    Java中的Tree数据结构详解 在Java编程语言中,树是一种非常重要的非线性数据结构,它模拟了自然界中的树状结构。...通过深入学习和实践,开发者可以更好地利用这些数据结构优化程序的性能和逻辑。

    java集合类学习汇总

    Java集合类是Java编程语言中用于存储对象的重要工具,它们提供了灵活的数据组织方式,使得开发者可以高效地管理和操作数据。...通过深入学习和实践,我们可以提高代码的效率和可维护性,更好地应对各种编程挑战。

    java中Collection深入剖析

    在Java编程语言中,`Collection`是所有集合框架的基础接口,它是`List`、`Set`和`Queue`等具体集合类型的父接口。本篇文章将深入剖析Java...通过深入学习和实践,你可以更好地驾驭这个强大的工具集,提升你的编程能力。

    Java语言程序设计-进阶篇-原书第8版

    2. Java集合框架:深入学习List、Set、Map等集合接口的实现类,如ArrayList、LinkedList、HashSet、TreeSet、HashMap、TreeMap等。理解它们的内部结构、性能差异以及如何根据应用场景选择合适的集合。 3. 异常处理...

    Java入门电子书

    4. **集合框架**:深入学习Java集合框架,包括List(ArrayList、LinkedList等)、Set(HashSet、TreeSet等)和Map(HashMap、TreeMap等)接口及其实现类的使用,理解它们之间的区别和应用场景。 5. **输入/输出流**...

    集合框架学习笔记

    集合框架是Java编程语言中的核心组成部分,它提供了一套高效、灵活的数据结构和算法操作,使得程序员能够方便地存储和管理对象。...通过深入学习和实践,我们可以更加熟练地运用这些工具,解决各种复杂的问题。

    初级JAVA PPT教程,适用于初级学者。忘珍惜

    Java是世界上最流行的编程语言之一,尤其在企业级应用开发中占据主导地位。对于初学者来说,理解并掌握Java的基础知识至关重要。...通过学习这些内容,初级学者能够为深入学习Java打下坚实的基础。

    class MyComparator implements Comparator类的算法 java

    在这个阶段,学习者可能已经接触了基础的Java集合框架,现在正在深入理解如何根据业务需求定制排序逻辑。 总结一下,`MyComparator`是自定义排序逻辑的一个示例,它实现了`Comparator`接口,允许我们控制对象的排序...

    会议内部学习资料相关文档

    通过深入学习,开发者能够增强其编程能力,优化项目管理,提升软件质量和效率。 【Java知识点详解】 1. **Java基础**:Java是一种面向对象的编程语言,具有跨平台性、安全性以及高性能的特点。学习Java的基础包括...

    JavaOOP深入集合框架上PPT教案学习.pptx

    Java的集合框架是Java编程中不可或缺的一部分,它为组织和管理对象提供了强大的工具。本教程主要探讨了Java OOP...通过深入学习这些接口和实现类,开发者能够更好地设计和实现各种数据结构,以适应复杂的应用场景。

Global site tag (gtag.js) - Google Analytics