「Java基础」关于Set的子类,HashSet与TreeSet

HashSet与TreeSet

Set是Collection的子接口,与它同级的接口还有List、Queue;

关于Set,它的显著性特征就是,无法记录数据存储的先后顺序,无法存储重复元素进入数据集合;

接下来介绍下HashSet与TreeSet

一、关于HashSet

1.hashset的存储特点?

无序性、单元性

2. HashSet是如何做到不去记录相同的元素呢?

通过了两个判断,第一个:通过HashCode;第二个:通过equals完成;

更近一步解释的:
(1)当我们创建出了一个新的HashSets,向内传入数据时,我们需要计算出HashCode值出来,计算方式我们可以自定义。

(2)将新传入的数据计算出HashCode值,之后与集合内的每个进行比较,会出现两种情况:

A:新HashCode值未出现,则直接将新值插入到集合。

B:新HashCode值出现过,则进行equals判断,将新插入元素与已存在的元素进行equals判断,这时也会出现两种结果:

C:返回ture,两个元素相同,则不会插入新值。

D:返回False,两个元素虽然HashCode值相同,但是元素本身并不相同,选择插入新元素。
import java.util.HashSet;
import java.util.Iterator;

class hashSetDemo
{
    public static void main(String[] args)
    {
        HashSet a = new HashSet();

        a.add(new Person("wangziyu01", 23));
        a.add(new Person("wangziyu01", 23));// 重复
        a.add(new Person("wangziyu02", 24));
        a.add(new Person("wangziyu03", 25));
        a.add(new Person("wangziyu04", 26));
        a.add(new Person("wangziyu04", 26));// 重复 hashset重复元素进行两次判断:hashCode值判断+equals内容判断
        Iterator it = a.iterator();
        while (it.hasNext())
        {
            Person p = (Person)it.next();
            sop(p.getName()+"..."+p.getAge());// 打印结果
        }
    }
    public static void sop(Object obj)
    {
        System.out.println(obj);
    }
}
class Person // 定义 equals比较方法 + hashCode计算方法
{
    private String name;
    private int age;
    Person(String name, int age)
    {
        this.name = name;
        this.age = age;
    }
    public boolean equals(Object obj)  //定义equals比较方法
    {
        if(!(obj instanceof Person))
            return false;
        Person p = (Person)obj;
        System.out.println(this.name+"..hashCode相同时,执行equals比较内容.."+p.name);
        return this.name.equals(p.name) && this.age == p.age;
    }
    public String getName()
    {
        return name;
    }
    public int getAge()
    {
        return age;
    }
    public static void sop(Object obj)
    {
        System.out.println(obj);
    }
    public int hashCode() {  //定义hashCode计算方法
        System.out.println(this.name + "....计算hashCode");
        return name.hashCode() + age * 37;
    }
}

最后打印出来的结果解释:
wangziyu01…计算hashCode
wangziyu01…计算hashCode
wangziyu01…hashCode相同时,执行equals比较内容…wangziyu01 // equals比较结果相同,进行剔除
wangziyu02…计算hashCode
wangziyu03…计算hashCode
wangziyu04…计算hashCode
wangziyu04…计算hashCode
wangziyu04…hashCode相同时,执行equals比较内容…wangziyu04 // equals比较结果相同,进行剔除

最终结果:
wangziyu04…26
wangziyu01…23
wangziyu03…25
wangziyu02…24

3 HashSet总结:

(1)数据结构为哈希表,线程为非同步

(2)保证元素唯一性的原理:判断元素的hashCode值是否相同,如果相同,还会继续判断元素的equals方法,是否为true。

(3)HashCode的计算方法与equals方法可以在对象中自定义,而不需要管如何调用,它是自动的

(4) HashSet数据集无法记录存储顺序。

(5)HashSet数据集无法存储相同元素。

二、关于TreeSet:

基本介绍:TreeSet是Set下子类,TreeSet会对传入的数据进行排序。
TreeSet的底层数据为二叉树结构,使用到了compareTo方法return 0;来保证元素的唯一性。

1. TreeSet排序前需要准备哪些? 需要怎么指定排序方式?

需要让数据具有可比性:
(1)方式一:让元素自身具备比较性。

解释:元素自身实现Compareable接口(例如:学生对象的数据,让它实现可比性),之后覆盖compareTo方法,在这个方法中指定返回值,比较无非三种情况:当新加入数据比较结果较大时,返回1;当新加入数据比较结果较小时,返回-1;相同时返回0;

下面是方式一的体现结果,让Person具有可比性:

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

        ts.add(new Student("lisi02",22));
        ts.add(new Student("lisi007",20));
        ts.add(new Student("lisi09",19));
        ts.add(new Student("lisi08",19));
        ts.add(new Student("lisi007",20)); // 重复元素
        //ts.add(new Student("lisi01",40));

        Iterator it = ts.iterator();
        while(it.hasNext())
        {
            Student stu = (Student)it.next();
            System.out.println(stu.getName()+"..."+stu.getAge());
        }
    }
}


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)
    {

        //return 0;

        if(!(obj instanceof Student))
            throw new RuntimeException("不是学生对象");
        Student s = (Student)obj;

        System.out.println(this.name+"....compareto....."+s.name);
        if(this.age>s.age)
            return 1;
        if(this.age==s.age)
        {
            return this.name.compareTo(s.name);
        }
        return 1;
        /**/
    }

    public String getName()
    {
        return name;

    }
    public int getAge()
    {
        return age;
    }
}

打印结果为:
lisi02…compareto…lisi02
lisi007…compareto…lisi02 // 插入元素与集合已存在的进行比较
lisi09…compareto…lisi02
lisi09…compareto…lisi007
lisi08…compareto…lisi007
lisi08…compareto…lisi09
lisi007…compareto…lisi007 //查询到了相同的元素准备插入,
lisi02…22
lisi007…20
lisi08…19
lisi09…19

(2)方式二:让集合自身具备比较性。

解释:当元素自身不具备比较性时,或者具备的比较性不是所需要的,在集合初始化时,就有了比较方式。

具体做法:我们需要定义一个新的类,让这个类实现Comparator接口,覆盖compare方法利用compareTo比较(继续返回1,0,-1)排序,将类名传入建立好的TreeSet内,完成集合具备比较性。

// 一个例子,给指定不同长度的字符依照长短进行排序
// 问题一:当字符串的长度相同时?也需要存储
// 问题二:怎么确定主条件与副条件?
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;

public class TreeSetDemo2 {
    public static void main(String[] args)
    {
        TreeSet ts = new TreeSet(new StringLenthComparator()); // 传入比较器
        ts.add("b");
        ts.add("cd");
        ts.add("qwer");
        ts.add("efr");
        ts.add("zzzzz");
        ts.add("qqqqq");

        Iterator it = ts.iterator();

        while (it.hasNext())
        {
            System.out.println(it.next());
        }
    }
}

class StringLenthComparator implements Comparator
{
    public int compare(Object o1, Object o2)
    {
        String s1 = (String) o1;
        String s2 = (String) o2;

        int num = new Integer(s1.length()).compareTo(new Integer(s2.length())); //主条件
        if(num==0)
            return s1.compareTo(s2); // 长度相同之后的副条件

        return num;
    }
}

结果:
b
cd
efr
qwer
qqqqq
zzzzz // 依据副条件判断可以插入

总结HashSet与TreeSet

共同点:
  • 它们都用到了迭代器比较方法
  • 他们都是集合框架中的成员,有自己独有方法
  • 都具有无序性与单元性
不同点:
  • HashSet方法:使用的方法是,让元素先具有比较性,先比较HashCode是否一致,如果一致进行equals()比较,返回False则插入这个新的元素
  • TreeSet方法:
    • (1)使用接口Comparable让元素具有比较性,进行比较。
    • (2)写新类继承Comparator复写compare方法(其中使用compareTo),让集合具有比较性,之后将比较器传入TreeSet中。
  • HashCode底层为哈希表,TreeSet底层为二叉树(红黑树)结构
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值