热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

黑马程序员:Java基础——Set集合之TreeSet

-------JavaEE培训、java培训、期待与您交流!----------1.概念TreeSet:可以对Set集合中的元素进行排序与HashSet方法一致,示例如下:<pre>
------- Java EE培训、 java培训、期待与您交流! ----------
1.概念

TreeSet:可以对Set集合中的元素进行排序

与HashSet方法一致,示例如下:

import java.util.Iterator;
import java.util.TreeSet;

import com.micronote.list.collection.SystemOutPrintClass;

public class TreeSetDemo extends SystemOutPrintClass{
public static void main(String[] args) {
TreeSet ts = new TreeSet();
ts.add("nnzi");
ts.add("mjdk");
ts.add("njdi");
ts.add("nnnb");

for(Iterator it = ts.iterator();it.hasNext();){
sopln(it.next());
}
}
}

需要注意的是,我已经将打印的两种方法封装起来,让这个类继承SystemOutPrintClass就会出现sop()以及sopln()方法。

输出结果为:

mjdk
njdi
nnnb
nnzi

我们可以看到,TreeSet并没有按照我们输入的先后顺序进行排序,而是通过ASCII码进行排序。

2.扩展练习

同样的我们给TreeSet集合中填入自定义集合。要求也与前面的ArrayList相同。

根据这个我们编出代码,可是运行结果却是让我们诧异:

我们看到出现了ClassCastException,为什么呢?因为,我们传入的是对象,对象和对象并没有可比性,JVN不知道该怎么比较于是就抛出了异常。

我们找到Comparable接口:


Comparable是这样解释的:

此接口强行对实现它的每个类的对象进行整体排序。这种排序被称为类的自然排序,类的 compareTo 方法被称为它的自然比较方法

接口里面只有一个方法——compareTo()返回类型为int型。

那么我们只需要让我们的对象类实现Comparable就可以实现重写compareTo方法了。

我们依照年龄排序,当年龄相同时在依照姓名排序:

@Override
public int compareTo(Object o) {
if(!(o instanceof Student)){
throw new RuntimeException("不是学生对象");
}
Student s = (Student)o;

if(this.iAge-s.iAge!=0){
return this.iAge-s.iAge;
}else{
return this.sName.compareTo(s.sName);
}
}

当我们再次运行的时候,发现所有项目已经存进来而且去除了重复项。以下是完整代码:

import java.util.Iterator;
import java.util.TreeSet;

import com.micronote.list.collection.SystemOutPrintClass;

public class TreeSetTest extends SystemOutPrintClass{
public static void main(String[] args) {
TreeSet ts = new TreeSet();

ts.add(new Student("lisi001",21));
ts.add(new Student("lisi02",22));
ts.add(new Student("lisi20",20));
ts.add(new Student("lisi021",21));
ts.add(new Student("lisi001",21));

for(Iterator it = ts.iterator();it.hasNext();){
Student stu = (Student)it.next();
sopln("Name:"+stu.getsName()+",Age:"+stu.getiAge());
}
}

}

class Student implements Comparable{

private String sName;
private int iAge;

Student(){}
Student(String sName,int iAge){
this.sName = sName;
this.iAge = iAge;
}

@Override
public int compareTo(Object o) {
if(!(o instanceof Student)){
throw new RuntimeException("不是学生对象");
}
Student s = (Student)o;

if(this.iAge-s.iAge!=0){
return this.iAge-s.iAge;
}else{
return this.sName.compareTo(s.sName);
}
}

public String getsName() {
return sName;
}
public void setsName(String sName) {
this.sName = sName;
}
public int getiAge() {
return iAge;
}
public void setiAge(int iAge) {
this.iAge = iAge;
}
}

需要注意的是: 我的打印方法已经包装成了SystemOutPrintClass。以下是运行结果:

Name:lisi20,Age:20
Name:lisi001,Age:21
Name:lisi021,Age:21
Name:lisi02,Age:22

3.TreeSet的数据结构

通过上一节的例子,我们来看一下TreeSet的数据结构。TreeSet的底层数据结构是二叉树,存取方式如图所示:


我们把左边的Student对象依次存入TreeSet集合中,同样按照年龄排序,那么存储时小数存到左面,大数存到右面,以二叉的形式来存储数据。当读取时,会像图中蓝色数字顺序读取。那么我们看到的就是已经排过序的元素。

为了保证元素唯一性的依据;compareTo方法return 0.

TreeSet排序的第一种方式:让元素自身具备比较性。元素需要实现Comparable接口,覆盖compareTo方法。这种方式也称为元素的自然顺序,或者叫做默认顺序。

4.实现Comparator方式排序

刚才说了TreeSet排序的一种方式,还有一种方式:

TreeSet排序的第二种方式:当元素自身不具备比较性时,或者具备的比较性不是所需要的。这时就需要让集合自身具备比较性。

在java.util包中有一个Comparator接口,这个接口强行对某个对象 collection 进行整体排序 的比较函数。

我们以上一节代码为基础,新建一个类,以下是全部代码:

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

import com.micronote.list.collection.SystemOutPrintClass;

public class TreeSetDemo2 extends SystemOutPrintClass{
public static void main(String[] args) {
TreeSet ts = new TreeSet(new MyCompare());

ts.add(new Student("lisi001",21));
ts.add(new Student("lisi02",22));
ts.add(new Student("lisi20",20));
ts.add(new Student("lisi021",21));
ts.add(new Student("lisi001",22));

for(Iterator it = ts.iterator();it.hasNext();){
Student stu = (Student)it.next();
sopln("Name:"+stu.getsName()+",Age:"+stu.getiAge());

}
}
}

class MyCompare implements Comparator{

@Override
public int compare(Object o1, Object o2) {
Student s1 = (Student)o1;
Student s2 = (Student)o2;

int iNum = s1.getsName().compareTo(s2.getsName());
if(iNum!=0){
return iNum;
}else{
return new Integer(s1.getiAge()).compareTo(new Integer((s2.getiAge())));
/*if(s1.getiAge()!=s2.getiAge()){
return s1.getiAge()-s2.getiAge();
}else{
return 0;
}*/
}
}
}


运行结果如下:

Name:lisi001,Age:21
Name:lisi001,Age:22
Name:lisi02,Age:22
Name:lisi021,Age:21
Name:lisi20,Age:20

通过运行我们发现:

定义了比较器,将比较其对象作为参数传递给TreeSet集合的构造函数。
当两种排序都存在时,以比较器为主。我们可以这么理解,集合也调用过Comparable进行了排序,后来又被Comparator的排序覆盖掉了。
定义一个类,实现Comparator接口,覆盖compare方法。

5.TreeSet练习

练习:按照字符串长度排序。

分析:字符串本身具备比较性,但是它的比较方式不是所需要的。

          使用Comparator会更方便

代码一:

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

import com.micronote.list.collection.SystemOutPrintClass;

public class TreeSetTest2 extends SystemOutPrintClass{
public static void main(String[] args) {
TreeSet ts = new TreeSet(new CompareStrLength());
ts.add("abcd");
ts.add("cc");
ts.add("bcdef");
ts.add("bb");
ts.add("cde");
ts.add("defghi");

for(Iterator it = ts.iterator();it.hasNext();){
sopln(it.next());
}
}
}

class CompareStrLength implements Comparator{

@Override
public int compare(Object o1, Object o2) {
String s1 = (String)o1;
String s2 = (String)o2;

int iNum = new Integer(s1.length()).compareTo(s2.length());
if(iNum==0){
return s1.compareTo(s2);
}else{
return iNum;
}
}
}

代码二(匿名内部类);

import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

import com.micronote.list.collection.SystemOutPrintClass;

public class TreeSetTest3 extends SystemOutPrintClass {
 public static void main(String[] args) {
  TreeSet ts = new TreeSet(new Comparator() {
   @Override
   public int compare(Object o1, Object o2) {
    String s1 = (String) o1;
    String s2 = (String) o2;

    int iNum = new Integer(s1.length()).compareTo(s2.length());
    if (iNum == 0) {
     return s1.compareTo(s2);
    } else {
     return iNum;
    }
   }
  });
  ts.add("abcd");
  ts.add("cc");
  ts.add("bcdef");
  ts.add("bb");
  ts.add("cde");
  ts.add("defghi");

  for (Iterator it = ts.iterator(); it.hasNext();) {
   sopln(it.next());
  }
 }
}

运行结果为:

bb
cc
cde
abcd
bcdef


推荐阅读
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Oracle seg,V$TEMPSEG_USAGE与Oracle排序的关系及使用方法
    本文介绍了Oracle seg,V$TEMPSEG_USAGE与Oracle排序之间的关系,V$TEMPSEG_USAGE是V_$SORT_USAGE的同义词,通过查询dba_objects和dba_synonyms视图可以了解到它们的详细信息。同时,还探讨了V$TEMPSEG_USAGE的使用方法。 ... [详细]
  • Whatsthedifferencebetweento_aandto_ary?to_a和to_ary有什么区别? ... [详细]
  • HashMap的相关问题及其底层数据结构和操作流程
    本文介绍了关于HashMap的相关问题,包括其底层数据结构、JDK1.7和JDK1.8的差异、红黑树的使用、扩容和树化的条件、退化为链表的情况、索引的计算方法、hashcode和hash()方法的作用、数组容量的选择、Put方法的流程以及并发问题下的操作。文章还提到了扩容死链和数据错乱的问题,并探讨了key的设计要求。对于对Java面试中的HashMap问题感兴趣的读者,本文将为您提供一些有用的技术和经验。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 本文介绍了Java工具类库Hutool,该工具包封装了对文件、流、加密解密、转码、正则、线程、XML等JDK方法的封装,并提供了各种Util工具类。同时,还介绍了Hutool的组件,包括动态代理、布隆过滤、缓存、定时任务等功能。该工具包可以简化Java代码,提高开发效率。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • 本文介绍了Python爬虫技术基础篇面向对象高级编程(中)中的多重继承概念。通过继承,子类可以扩展父类的功能。文章以动物类层次的设计为例,讨论了按照不同分类方式设计类层次的复杂性和多重继承的优势。最后给出了哺乳动物和鸟类的设计示例,以及能跑、能飞、宠物类和非宠物类的增加对类数量的影响。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 模板引擎StringTemplate的使用方法和特点
    本文介绍了模板引擎StringTemplate的使用方法和特点,包括强制Model和View的分离、Lazy-Evaluation、Recursive enable等。同时,还介绍了StringTemplate语法中的属性和普通字符的使用方法,并提供了向模板填充属性的示例代码。 ... [详细]
  • Java程序设计第4周学习总结及注释应用的开发笔记
    本文由编程笔记#小编为大家整理,主要介绍了201521123087《Java程序设计》第4周学习总结相关的知识,包括注释的应用和使用类的注释与方法的注释进行注释的方法,并在Eclipse中查看。摘要内容大约为150字,提供了一定的参考价值。 ... [详细]
author-avatar
黑小羊Mark
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有