论文部分内容阅读
摘要:本文基于集合学习,介绍如何设计一个比较完善的应用类。通过HashSet介绍了在应用类中添加equals0方法和hashCode()方法,通过TreeSa介绍了应用类需要实现Comparable接口并实现继承的compareTo()方法。
关键词:集合;类;教学设计
中图分类号:G642 文献标识码:A
文章编号:1009-3044(2019)27-0087-02
集合(Set)是Java中一个很重要的可以用来存储和处理无重复元素的高效的数据结构。比如说可以存储和处理一个单位的部门名称,存储和处理一个国家的省城名称,或者奥运会时参赛国家的名称等,这几个信息的处理都是要求不可重复的。那么在实际应用中,使用集合存储和处理相关问题时,应该如何设计这个应用类,确保其元素不可重复存储呢?
1集合Set
集合Set是一个接口,它继承了Collection接口中所有的方法。Set接口本身不能实例化,但是可以作为类型使用,只是规定其实例不能包含重复的元素。在一个集合中,当要添加一个新元素时,要先判断这个元素的散列码(hashcode值)在原集合的哈希表中是否存在。如果不存在,则新元素可以立即加入;如果存在,则再检查equals()方法,即新元素通过调用其自身的equals()方法,跟原集合中所有的元素都进行比较,如果存在结果为true的情况,则新元素不能加入,否则新元素可以加入。
Set有三个实现的具体的子类,分别是HashSet、Hnked-HashSet和TreeSet,这三个类也是必须确保不能向集合中添加重复的元素。关于集合的操作与访问是集合教学的一个重要方面,但是本文限于篇幅不作特别介绍。
2散列集HashSet
HashSet是一个实现了Set接口的散列集,可以使用它的无参构造方法来创建空的散列集,也可以由一个现有的集合来创建一个散列集。HashSet类的实例用来存储互不相同的任何元素,但允许null元素。该集合的元素是无序的、高效率的。在教学过程中,为让学生理解这个特点,会创建一个HashSet实例,存放一些字符串对象并输出集合,具体见【示例1】。
【示例1】主要代码如下:
Set set=Hew HashSet();//创建一个空集合,可以放任何对象
set.add(”南京“)//将字符串对象“南京”存人集合set中
set.add(”南京”);//这个“南京”不会重复存入集合中;
set.add(“Nanjing”);//将字符串对象“Nanjing”存人集合set中
set.add(“nanjing”);//将字符串对象“nanjing”存人集合set中,注意与“Nanjing”不同
setl.add(12);//12会被包装成对象存入集合set中,
svstem.out.println(setl;//输出集合set中所有元素
上述程序代码最终运行结果显示集合中只有“南京、Nan-jing、nanjing、12”这四个元素。多次运行,会发现次序有变化,但是元素不变。能达到这效果的原因是,String类已经重写了equal()方法与hashCode()方法,排除了重复的元素。
那么如果集合set中存储圆类对象,能确保不重复吗?首先设计【示例2】圆类如下:
class Circle{
private double r;
Circle(double r){this.r=r;}
//省略r的get、set方法与求面积与周长等其他方法;
pubhc String toString0{return”r=” r;}//重写这个方法,显示圆对象信息
}
在【示例1】的最后输出语句之前添加两行相同的代码"set.add(new Cirlce(5));”
重新运行【示例1】程序,会发现输出的集合元素中会出现两个“r=5.0”:
为避免上述问题,需要改写【示例2】的Cidce类,重写equals()方法与hashCode()方法。在讲授这个集合内容之前,学生已经掌握了如何正确写出Circle类的equals方法。由此可以先让学生在Cirlce类中正确添加equals()方法后,再次运行【示例1】,发现两个半径为5的圆依然存在。说明一个类仅仅重写equals()方法是不够的,必须还要重写hashCode()方法。该方法原型如下:
public int hashCode(){}
hashCode()方法其实就是要求返回一个整型的散列码(hashCode值)。要求相同对象的散列码一样即可,意味着不相同的元素的散列码可以一样也可以不一样。对于一个由半径值来描述圆的对象,半径相同其散列码相同即可。那么直接将半径取整返回即可,hashCode()方法代码如下:
pubhc im hashCode(){return(inI)r;}
上述代码表示,假如圆半径的整数部分相同,则它们的散列码相同,在集合中会再去处理equals方法,才能判断它们究竟算不算相同的对象。例如半径为5.00000-5.99999,它们的散列码都是5。如果圆半径精度要求达到4位小数,那么为了提高效率,可以考虑把半径值扩大后再取整返回即可,修改代码如下:
public im hashCode(){return(inI)(r*10000);}
当然还有其他方法,可以利用String类中已经实现的hash-Code()方法,把double类型的r转换成String类型,则可以直接调用其本身的hashCodeO方法即可。因此Circle类中的hashCode()方法还可以修改如下:
public int hashCode0{return(r ””).hashCode();J
在教学过程中发现,学生重写某个类的hashCode方法总是不知如何下手,其实只要确保某元素重要属性值相同,其散列码相同即可。想办法把类中描述元素的重要属性值转换成整型数据返回或转换成字符串调用其hashCode()方法返回即可,非常简单。
3链式集合LinkedHashSet
LinkedHashSet是HashSet的子类,它支持集合内的元素是有序的,不过这个次序是按照集合添加元素的次序的方式排序的。复制【示例1】得到【示例3】,并修改第一行代码:
Set set=new LinkedHashSet();
其余代碼不变,运行【示例3】,多次运行,发现输出的集合中的元素没有重复,且与添加的顺序一致,这个特点学生还是比较容易理解并接受的。
4树形集合TreeSet
Set接口的一个子接口SortedSet可以确保集合中的元素是有序的。TreeSet实现了SortedSet接口,通过无参构造方法可以创建一个空的TreeSet对象。只要对象是可以比较的,就可以将它们添加到一个TreeSet对象中。先设计一个只能添加字符串对象的TreeSet对象,让学生理解TreeSet与HashSet的不同特点。
【示例4】主要代码如下:
Setset=new TreeSet();//考虑集合只能存人String对象
set.add("naniing");
在实际应用中,如果需要用集合来存储和处理对象,则该对象的原类除了包含正常封装的数据成员,一些必要的业务处理的方法外,还需要重写hashCode()和equals()方法;如果业务上还要求需要有序存储,那么对象的原类还必须实现compara-ble接口,实现从接口继承的compareTo()方法。通过集合基本特点的介绍,希望大家对如何设计一个相对比较完善的应用类能有所帮助。
【通联编辑:光文玲】
关键词:集合;类;教学设计
中图分类号:G642 文献标识码:A
文章编号:1009-3044(2019)27-0087-02
集合(Set)是Java中一个很重要的可以用来存储和处理无重复元素的高效的数据结构。比如说可以存储和处理一个单位的部门名称,存储和处理一个国家的省城名称,或者奥运会时参赛国家的名称等,这几个信息的处理都是要求不可重复的。那么在实际应用中,使用集合存储和处理相关问题时,应该如何设计这个应用类,确保其元素不可重复存储呢?
1集合Set
集合Set是一个接口,它继承了Collection接口中所有的方法。Set接口本身不能实例化,但是可以作为类型使用,只是规定其实例不能包含重复的元素。在一个集合中,当要添加一个新元素时,要先判断这个元素的散列码(hashcode值)在原集合的哈希表中是否存在。如果不存在,则新元素可以立即加入;如果存在,则再检查equals()方法,即新元素通过调用其自身的equals()方法,跟原集合中所有的元素都进行比较,如果存在结果为true的情况,则新元素不能加入,否则新元素可以加入。
Set有三个实现的具体的子类,分别是HashSet、Hnked-HashSet和TreeSet,这三个类也是必须确保不能向集合中添加重复的元素。关于集合的操作与访问是集合教学的一个重要方面,但是本文限于篇幅不作特别介绍。
2散列集HashSet
HashSet是一个实现了Set接口的散列集,可以使用它的无参构造方法来创建空的散列集,也可以由一个现有的集合来创建一个散列集。HashSet类的实例用来存储互不相同的任何元素,但允许null元素。该集合的元素是无序的、高效率的。在教学过程中,为让学生理解这个特点,会创建一个HashSet实例,存放一些字符串对象并输出集合,具体见【示例1】。
【示例1】主要代码如下:
Set set=Hew HashSet();//创建一个空集合,可以放任何对象
set.add(”南京“)//将字符串对象“南京”存人集合set中
set.add(”南京”);//这个“南京”不会重复存入集合中;
set.add(“Nanjing”);//将字符串对象“Nanjing”存人集合set中
set.add(“nanjing”);//将字符串对象“nanjing”存人集合set中,注意与“Nanjing”不同
setl.add(12);//12会被包装成对象存入集合set中,
svstem.out.println(setl;//输出集合set中所有元素
上述程序代码最终运行结果显示集合中只有“南京、Nan-jing、nanjing、12”这四个元素。多次运行,会发现次序有变化,但是元素不变。能达到这效果的原因是,String类已经重写了equal()方法与hashCode()方法,排除了重复的元素。
那么如果集合set中存储圆类对象,能确保不重复吗?首先设计【示例2】圆类如下:
class Circle{
private double r;
Circle(double r){this.r=r;}
//省略r的get、set方法与求面积与周长等其他方法;
pubhc String toString0{return”r=” r;}//重写这个方法,显示圆对象信息
}
在【示例1】的最后输出语句之前添加两行相同的代码"set.add(new Cirlce(5));”
重新运行【示例1】程序,会发现输出的集合元素中会出现两个“r=5.0”:
为避免上述问题,需要改写【示例2】的Cidce类,重写equals()方法与hashCode()方法。在讲授这个集合内容之前,学生已经掌握了如何正确写出Circle类的equals方法。由此可以先让学生在Cirlce类中正确添加equals()方法后,再次运行【示例1】,发现两个半径为5的圆依然存在。说明一个类仅仅重写equals()方法是不够的,必须还要重写hashCode()方法。该方法原型如下:
public int hashCode(){}
hashCode()方法其实就是要求返回一个整型的散列码(hashCode值)。要求相同对象的散列码一样即可,意味着不相同的元素的散列码可以一样也可以不一样。对于一个由半径值来描述圆的对象,半径相同其散列码相同即可。那么直接将半径取整返回即可,hashCode()方法代码如下:
pubhc im hashCode(){return(inI)r;}
上述代码表示,假如圆半径的整数部分相同,则它们的散列码相同,在集合中会再去处理equals方法,才能判断它们究竟算不算相同的对象。例如半径为5.00000-5.99999,它们的散列码都是5。如果圆半径精度要求达到4位小数,那么为了提高效率,可以考虑把半径值扩大后再取整返回即可,修改代码如下:
public im hashCode(){return(inI)(r*10000);}
当然还有其他方法,可以利用String类中已经实现的hash-Code()方法,把double类型的r转换成String类型,则可以直接调用其本身的hashCodeO方法即可。因此Circle类中的hashCode()方法还可以修改如下:
public int hashCode0{return(r ””).hashCode();J
在教学过程中发现,学生重写某个类的hashCode方法总是不知如何下手,其实只要确保某元素重要属性值相同,其散列码相同即可。想办法把类中描述元素的重要属性值转换成整型数据返回或转换成字符串调用其hashCode()方法返回即可,非常简单。
3链式集合LinkedHashSet
LinkedHashSet是HashSet的子类,它支持集合内的元素是有序的,不过这个次序是按照集合添加元素的次序的方式排序的。复制【示例1】得到【示例3】,并修改第一行代码:
Set set=new LinkedHashSet();
其余代碼不变,运行【示例3】,多次运行,发现输出的集合中的元素没有重复,且与添加的顺序一致,这个特点学生还是比较容易理解并接受的。
4树形集合TreeSet
Set接口的一个子接口SortedSet可以确保集合中的元素是有序的。TreeSet实现了SortedSet接口,通过无参构造方法可以创建一个空的TreeSet对象。只要对象是可以比较的,就可以将它们添加到一个TreeSet对象中。先设计一个只能添加字符串对象的TreeSet对象,让学生理解TreeSet与HashSet的不同特点。
【示例4】主要代码如下:
Setset=new TreeSet();//考虑集合只能存人String对象
set.add("naniing");
在实际应用中,如果需要用集合来存储和处理对象,则该对象的原类除了包含正常封装的数据成员,一些必要的业务处理的方法外,还需要重写hashCode()和equals()方法;如果业务上还要求需要有序存储,那么对象的原类还必须实现compara-ble接口,实现从接口继承的compareTo()方法。通过集合基本特点的介绍,希望大家对如何设计一个相对比较完善的应用类能有所帮助。
【通联编辑:光文玲】