您的位置:首页 > 编程语言 > Java开发

Java学习——Set使用方法以及HashSet和TreeSet的区别,深入理解HashSet如何判断元素是否重复

2019-08-16 14:58 1556 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/leilei7407/article/details/99639895

java学习——Set使用方法以及HashSet和TreeSet的区别

Set为无序集合(无序是指存入元素的先后顺序与输出元素的先后顺序不一致),不允许添加重复元素。Set是个接口,不能直接实例化对象,即Set s=new Set()是错误的。

Set的实现类常用的有:HashSet和TreeSet。

1.HashSet和TreeSet的区别:

(1)HashSet是用哈希表(散列表结构)实现的。
HashSet会调用该对象的hashCode()方法来得到该对象的hashCode值,根据该值来找到对象的存储位置。然后和该位置上所有的元素进行equals比较,如果该位置没有其他元素或者比较的结果都为false就存进去,否则就不存。即元素是按照哈希值来找存储位置,所有无序,而且可以保证无重复元素
注意:若向HashSet中存储自定义对象时,需要重写hashCode()和equals()方法(不重写的话不会报错,但运行结果和想象不一样,见下面代码)。

深入理解HashSet集合对象如何判断数据元素是否重复:
判断待存对象hashCode值是否与集合中已有元素对象hashCode值相同,如果hashCode不同则表示不重复,不用执行equals()方法; 如果相同则再调用equals方法进行检查,equals返回false表示不重复,否则表示重复。
注意:Java中的hashCode值是由对象的地址所确定的,每一个地址对应一个值。Object类中的equals方法中比较的也是对象的地址值。

(2)TreeSet是用二叉树实现的。
TreeSet可以对Set集合中的元素进行排序,TreeSet中数据是自动排好序的。
TreeSet支持两种排序方式,自然排序和定制排序,其中自然排序为默认的排序方式。
若元素自身不具备比较功能,则需要实现Comparator接口,并覆盖其compare方法。

2.Set示例代码(使用HashSet实现)

下面代码中,集合中存放的不是自定义的存储对象,所以不需要重写HashCode()和equals()。

package demo;

import java.util.Date;
import java.util.HashSet;
import java.util.Set;

public class SetTest {

public static void main(String[] args) {

//声明一个Set集合对象sd,里面存放的全是Date类型的对象,
Set<Date> sd;
sd=new HashSet<Date>();

//输出当前的时间,运行结果为1565836065039
System.out.println(new Date().getTime());

//创建几个时间对象
Date a=new Date(1565836065039L);
Date b=new Date(1565835065039L);
Date c=new Date(1565834065039L);

//向集合中添加元素,add()方法返回值为boolean类型,若添加成功,返回true;否则为false
sd.add(a);
sd.add(b);
sd.add(c);

//Set中元素不能重复,从下面b1的值以及遍历的输出结果中可以看出。

boolean b1=sd.add(a);
System.out.println(b1);  //输出false

//遍历输出集合中的对象,输出3次。
for(Date dt:sd) {
System.out.println(dt);
}
}
}

3.使用HashSet完成自定义类型存储

下面代码中SetStudent类为自定义存储类型,需要重写HashCode()和equals()方法。
若不重写重写HashCode()和equals()方法,不会报错,但结果和想象中不太一样。如下代码所示
(注意下面代码中,用迭代器遍历自定义类型时,取值的使用方法)

package demo;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class SetStudent {

public String name;    //姓名
public String xuehao;  //学号
public int age;        //年龄

public SetStudent(String name,String xuehao,int age) {
this.name=name;
this.xuehao=xuehao;
this.age=age;
}

public static void main(String[] args) {

Set<SetStudent> s=new HashSet();
SetStudent s1=new SetStudent("王","B15",18);
SetStudent s2=new SetStudent("李","B16",19);
SetStudent s3=new SetStudent("王","B17",18);
SetStudent s4=new SetStudent("王","B17",18);
SetStudent s5=new SetStudent("王","B15",18);
SetStudent s6=new SetStudent("张","B15",20);
s.add(s1);
s.add(s2);
s.add(s3);
s.add(s4);
s.add(s5);
s.add(s6);
Iterator it=s.iterator();
while(it.hasNext()) {
SetStudent st=(SetStudent)it.next();
System.out.println(st.name+"、"+st.xuehao+"、"+st.age);
}
}

}

运行结果为:

王、B17、18
张、B15、20
王、B15、18
王、B15、18
李、B16、19
王、B17、18

从上面的运行结果可以看出,s4,s5,s6 也存入了集合中,而实际应该是学号是唯一的,s4,s5,s6不应该被存入集合中。
重写HashCode()和equals()方法后代码示例如下:
注意:两个方法都要重写。若SetStudent不重写equals()方法,则会调用父类Objcet中的equals()方法,而Object类中的equals方法中比较的是对象的地址值。

package demo;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class SetStudent {

public String name;    //姓名
public String xuehao;  //学号
public int age;        //年龄

public SetStudent(String name,String xuehao,int age) {
this.name=name;
this.xuehao=xuehao;
this.age=age;
}

//重写HashCode()方法
@Override
public int hashCode() {

return xuehao.hashCode();
}

//重写equals方法
@Override
public boolean equals(Object obj) {

SetStudent s=(SetStudent)obj;
return this.xuehao.equals(s.xuehao);
}

public static void main(String[] args) {

Set<SetStudent> s=new HashSet();
SetStudent s1=new SetStudent("王","B15",18);
SetStudent s2=new SetStudent("李","B16",19);
SetStudent s3=new SetStudent("王","B17",18);
SetStudent s4=new SetStudent("王","B17",18);
SetStudent s5=new SetStudent("王","B15",18);
SetStudent s6=new SetStudent("张","B15",20);
s.add(s1);
s.add(s2);
s.add(s3);
s.add(s4);
s.add(s5);
s.add(s6);
Iterator it=s.iterator();
while(it.hasNext()) {
SetStudent st=(SetStudent)it.next();//注意:此处不能直接 it.next().name,这种写法错误
System.out.println(st.name+"、"+st.xuehao+"、"+st.age);
}
}
}

运行结果为:

王、B15、18
李、B16、19
王、B17、18

3.Set示例代码(使用TreeSet实现)

package demo;

import java.util.Set;
import java.util.TreeSet;

public class TreeSetTest {

public static void main(String[] args) {

Set<Integer> s=new TreeSet(); //注意此处Integer不能换成int
s.add(2);
s.add(4);
s.add(3);
s.add(1);
s.add(2);  //插入失败,由运行结果也可看出

//使用for-each语句进行遍历
for(int i:s) {
System.out.println(i);
}
}
}

运行结果:

1
2
3
4

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐