Set集合中元素的保存问题(hashSet和treeSet中不能存放相同元素)
2014-11-15 12:28
387 查看
1.对于hashSet集合,一般需要覆写类中的hashCode()方法和equals()方法。
比如下面代码
name:liming---age:18
name:liming---age:18
name:zhangsan---age:21
由此可以看见hashSet中保存了两个内容相同的元素。为什么保存成功了呢?主要因为第一个方法hashCode()方法返回的是类的引用,引用当然是不相等的,所以系统就认为两者不等,所以就可以保存。
如果上面还不明白看下面代码:
打印结果为:
Student@6af62373
Student@459189e1
Student@3ce53108
java
说明str1和str2只保存了一个那是因为String类中已经覆写了hashCode() 和equals()方法,hashCode和equals都是相等的
所以若要使hashSet中存放不同的元素则必须对Student中的这两个方法进行覆写。
代码如下
也就是说对于hashSet保证元素唯一性的方法是通过覆盖元素的两个方法hashCode()和equals()方法来判断元素是否相等,如果hashCode()的值相等才会调用equals()方法,否则不会调用equals()方法,这样在一定程度上也提高了工作的效率,不用每次都调用equals()方法。
2.对于treeSet集合保证元素唯一性的方法主要有两个:
(1).使元素本身具备比较性,实现comparable接口,覆盖里面的compareTo()方法。
代码如下:
打印结果为:
name:liming---age:18
name:zhangsan---age:21
name:wangwu---age:27
需要注意的是对于treeSet如果实现comparable接口编译可以通过但运行会报错。如果覆盖compareTo()方法时直接在方法体内写return 0;则此时TreeSet只能保存第一个元素,其他的都存不进去,而如果return 1,则会把所有元素存进去,不按年龄顺序。这种方式也称为元素的自然排序,或者叫默认排序。
(2).定义一个类实现Comparator接口,覆盖compare()方法
代码如下:
如果两种排序都存在时,以比较器为准,如上如果Student中继承自comparable接口且尤其实现方法时,以下面定义的myCompare比较器为准。
比如下面代码
class testhash { public static void main(String[] args) { compare(); } public static void compare() { HashSet hs=new HashSet(); Student stu1=new Student("zhangsan",21); Student stu2=new Student("liming",18); Student stu3=new Student("liming",18); hs.add(stu1); hs.add(stu2); hs.add(stu3); Iterator it=hs.iterator(); while (it.hasNext()) { Student stu=(Student)it.next(); System.out.println("name:"+stu.getName()+"---age:"+stu.getAge()); } }打印结果为:
name:liming---age:18
name:liming---age:18
name:zhangsan---age:21
由此可以看见hashSet中保存了两个内容相同的元素。为什么保存成功了呢?主要因为第一个方法hashCode()方法返回的是类的引用,引用当然是不相等的,所以系统就认为两者不等,所以就可以保存。
如果上面还不明白看下面代码:
public static void compare() { HashSet hs=new HashSet(); Student stu1=new Student("zhangsan",21); Student stu2=new Student("liming",18); Student stu3=new Student("liming",18); String str1=new String("abc"); str1="java"; String str2="java"; hs.add(stu1); hs.add(stu2); hs.add(stu3); hs.add(str1); hs.add(str2); Iterator it=hs.iterator(); while (it.hasNext()) { //Student stu=(Student)it.next(); // System.out.println("name:"+stu.getName()+"---age:"+stu.getAge()); System.out.println(it.next()); } }
打印结果为:
Student@6af62373
Student@459189e1
Student@3ce53108
java
说明str1和str2只保存了一个那是因为String类中已经覆写了hashCode() 和equals()方法,hashCode和equals都是相等的
所以若要使hashSet中存放不同的元素则必须对Student中的这两个方法进行覆写。
代码如下
class Student { private String name; private int age; Student(String name,int age) { this.name=name; this.age=age; } //重写hashCode public int hashCode() { return age*name.hashCode(); } public boolean equals(Object obj) { if (!(obj instanceof Student)) return false; Student stu=(Student)obj; System.out.println(this.name+"----"+stu.name); boolean m=this.name.equals(stu.name)&&this.age==stu.age; return m; } public String getName() { return name; } public int getAge() { return age; } public void setName(String name) { this.name=name; } public void setAge(int age) { this.age=age; } } class testhash { public static void main(String[] args) { compare(); //test1(); } public static void compare() { HashSet hs=new HashSet(); Student stu1=new Student("zhangsan",21); Student stu2=new Student("liming",18); Student stu3=new Student("liming",18); hs.add(stu1); hs.add(stu2); hs.add(stu3); Iterator it=hs.iterator(); while (it.hasNext()) { Student stu=(Student)it.next(); System.out.println("name:"+stu.getName()+"---age:"+stu.getAge()); } } public static void test1() { String str1=new String("abc"); String str2="abc"; String s="hello"; s="java"; String s1="java"; System.out.println("-----"); System.out.println(s.equals(s1)); System.out.println(str1.equals(str2)); //二者的hashCode 是相等的 System.out.println(str1.hashCode()+"--"+str2.hashCode()); } }如此的话stu2和stu3就只保存了一个。
也就是说对于hashSet保证元素唯一性的方法是通过覆盖元素的两个方法hashCode()和equals()方法来判断元素是否相等,如果hashCode()的值相等才会调用equals()方法,否则不会调用equals()方法,这样在一定程度上也提高了工作的效率,不用每次都调用equals()方法。
2.对于treeSet集合保证元素唯一性的方法主要有两个:
(1).使元素本身具备比较性,实现comparable接口,覆盖里面的compareTo()方法。
代码如下:
class Student implements Comparable { private String name; private int age; Student(String name,int age) { this.name=name; this.age=age; } public int compareTo(Object obj) { if (!(obj instanceof Student)) throw new RuntimeException("不是学生类"); Student stu=(Student)obj; //最基本写法 if (this.age>stu.age) { return 1; } if (this.age==stu.age) { return this.name.compareTo(stu.name); } return -1; } public String getName() { return name; } public int getAge() { return age; } public void setName(String name) { this.name=name; } public void setAge(int age) { this.age=age; } } class testhash { public static void main(String[] args) { test1(); } public static void test1() { TreeSet ts=new TreeSet(); Student stu1=new Student("zhangsan",21); Student stu3=new Student("liming",18); Student stu4=new Student("wangwu",27); Student stu2=new Student("liming",18); ts.add(stu1); ts.add(stu2); ts.add(stu3); ts.add(stu4); Iterator it=ts.iterator(); while (it.hasNext()) { Student stu=(Student)it.next(); System.out.println("name:"+stu.getName()+"---age:"+stu.getAge()); } } }
打印结果为:
name:liming---age:18
name:zhangsan---age:21
name:wangwu---age:27
需要注意的是对于treeSet如果实现comparable接口编译可以通过但运行会报错。如果覆盖compareTo()方法时直接在方法体内写return 0;则此时TreeSet只能保存第一个元素,其他的都存不进去,而如果return 1,则会把所有元素存进去,不按年龄顺序。这种方式也称为元素的自然排序,或者叫默认排序。
(2).定义一个类实现Comparator接口,覆盖compare()方法
代码如下:
class testhash { public static void main(String[] args) { test1(); } public static void test1() { TreeSet ts=new TreeSet(new myCompare()); Student stu1=new Student("zhangsan",21); Student stu3=new Student("liming",18); Student stu4=new Student("wangwu",27); Student stu2=new Student("liming",18); ts.add(stu1); ts.add(stu2); ts.add(stu3); ts.add(stu4); Iterator it=ts.iterator(); while (it.hasNext()) { Student stu=(Student)it.next(); System.out.println("name:"+stu.getName()+"---age:"+stu.getAge()); } } } //定义一个类实现Comparator接口,覆盖compare()方法 class myCompare implements Comparator { public int compare(Object obj1,Object obj2) { Student stu1=(Student)obj1; Student stu2=(Student)obj2; int num=stu1.getName().compareTo(stu2.getName()); if (num==0) { return new Integer(stu1.getAge()).compareTo(new Integer(stu2.getAge())); } return num; } }
如果两种排序都存在时,以比较器为准,如上如果Student中继承自comparable接口且尤其实现方法时,以下面定义的myCompare比较器为准。
相关文章推荐
- 使用HashSet和TreeSet存储多个商品信息,遍历并输出;其中商品属性:编号,名称,单价,出版社;要求向其中添加多个相同的商品,验证集合中元素的唯一性。 提示:向HashSet中添加自定义
- java怎么判断两个Set 里的对象的值是否相同【两个set中的值是否相等】、java treeset和hashset如何判断元素是否相同【即对象是否完全相同;利用一个set去除重复元素】
- 集合框架_TreeSet的add()方法源码再次解读和TreeSet对元素排序的总结
- Java基础知识强化之集合框架笔记47:Set集合之TreeSet保证元素唯一性和比较器排序的原理及代码实现(比较器排序)
- 个性集合之TreeSet类的元素有序性排序和元素唯一性的特点
- 《java入门第一季》之集合框架TreeSet存储元素自然排序以及图解
- JAVA 获取Set集合和List集合中相同的元素
- set,map,list集合的交集差集存放相同值反转分割等-代码优雅之道Guava(三)
- list,set等集合遍历时,不能remove集合中的元素。需要new一个Object或者list,set,里面add需要删除的元素,等集合遍历完了进行remove(Object)或者removeAll(list/set)操作
- 黑马程序员------TreeSet集合框架存储自定义元素之排序Comparable与Comparator
- 0002_20170226_【我是菜鸟】_【Java】_HashSet中不能插入相同元素的原因
- STL集合容器set按照由小到大或者由大到小的顺序存放元素
- 黑马程序员_集合之Set(HashSet与TreeSet)
- java--集合框架的Hashset和Treeset
- 解决firefox保存winrar时不能勾选“以后自动采用相同的动作处理此类文件”的问题
- TreeSet集合的比较方式和元素唯一性的原理。
- 黑马程序员——TreeSet集合添加元素的原理
- 关于JAVA中两个list或者两个set集合取他们相同的元素
- 集合的特殊功能之TreeSet集合如何保证元素的唯一及排序的
- 《java入门第一季》之集合框架TreeSet存储元素自然排序以及图解