TreeSet和HashSet的不同之处(也是TreeMap和HashMap的不同之处)

TreeSet和HashSet的不同之处(也是TreeMap和HashMap的不同之处)

1)TreeSet和HashSet都是利用对应的Map的key值进行数据保存(TreeMap和HashMap,所以map的value肯定是可以为null的)
2)TreeMap是使用红黑树进行数据保存,HashMap是进行hash计算后存入数组+链表(或红黑树)

以上2点,大家只要学习过,都会记得,但是我要说的是,TreeSet保存的数据,必须是继承Comparable接口或者要设定好Comparator比较器的,就是说:TreeSet的数据必须是可以比较的,而HashMap是不用这样的设置的
HashSet比较两个对象的数值是否一致的标志是:两个值的equals后是否相同(1、是可以为null的,hashCode为0;2、HashSet实验到红黑树时候,也是要比较大小的,依次是比较hash值->compare->getClass().getName()->System.identityHashCode(identityHashCode是根据对象的地址计算得到的,所以任何两个不同的对象的identityHashCode值总是不相等),如果compare比较的结果是0不是按相同处理,而是进一步的比较,只要equals不同,就一定要比出胜负)
可以为null的,hashCode为0)
TreeSet比较两个对象的数值是否一致的标志是:两个值的compare后是否为0(因为要compare比较,所以TreeSet不能插入null)
所以,自然就会出现,相同一个list,放入不同的set中,得到的set的结果是不同的
如何才能避免这个问题呢,只需要保证实现了compareTo方法,就有必要实现equals方法,而且保证两个方法是同步的(即要么同时不等,要么同时相等)

//下面是测试例子compareTo只比较k值,equals只比较t值

public static void main(String[] args) {
    HashSet<NNNode> hashSet = new HashSet();
    TreeSet<NNNode> treeSet = new TreeSet<>();
    List<NNNode> list = getList();
    for (NNNode nnNode : list) {
        hashSet.add(nnNode);
        treeSet.add(nnNode);
    }
    System.out.println(hashSet.size());
    System.out.println(treeSet.size());
    System.out.println(hashSet);
    System.out.println(treeSet);
}

private static List<NNNode> getList() {
    List<NNNode> list = new ArrayList<>();
    list.add(new NNNode(0, 0));
    list.add(new NNNode(1, 0));
    list.add(new NNNode(2, 0));
    list.add(new NNNode(3, 0));
    list.add(new NNNode(4, 0));
    list.add(new NNNode(0, 1));
    list.add(new NNNode(0, 2));
    list.add(new NNNode(0, 3));
    return list;
}

static class NNNode implements Comparable<NNNode> {
    int k;
    int t;

    public NNNode(int k, int t) {
        this.k = k;
        this.t = t;
    }

    @Override
    public int hashCode() {
        return 0;
    }

    @Override
    public int compareTo(NNNode o) {
        return k - o.k;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o instanceof NNNode) {
            return t == ((NNNode) o).t;
        }
        return false;
    }

    @Override
    public String toString() {
        return "NNNode{" +
                "k=" + k +
                ", t=" + t +
                '}';
    }
}

结果就是

4
5
[NNNode{k=0, t=0}, NNNode{k=0, t=1}, NNNode{k=0, t=2}, NNNode{k=0, t=3}]
[NNNode{k=0, t=0}, NNNode{k=1, t=0}, NNNode{k=2, t=0}, NNNode{k=3, t=0}, NNNode{k=4, t=0}]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. ArrayList: - ArrayList是基于数组实现的动态数组,可以自动扩容,可以存储任何对象类。 - 数组的优点是可以随机访问元素,缺点是插入和删除元素时需要移动其他元素。 - ArrayList支持快速随机访问,但插入和删除元素的效率较低。 2. LinkedList: - LinkedList是基于链表实现的,每个节点包含一个指向前驱和后继节点的指针,可以存储任何对象类。 - 链表的优点是插入和删除元素时不需要移动其他元素,缺点是不能直接随机访问元素,需要遍历整个链表。 - LinkedList支持高效的插入和删除操作,但随机访问元素的效率较低。 3. TreeSet: - TreeSet是基于红黑树实现的有序集合,不允许重复元素,可以存储任何对象类。 - 红黑树的优点是能够自动排序,插入和删除元素的效率较高,缺点是随机访问元素的效率较低。 - TreeSet支持高效的插入、删除和查找操作,但随机访问元素的效率较低。 4. HashSet: - HashSet是基于哈希表实现的无序集合,不允许重复元素,可以存储任何对象类。 - 哈希表的优点是能够快速查找元素,缺点是元素的顺序是随机的。 - HashSet支持高效的插入、删除和查找操作,但不能保证元素的顺序。 5. HashMap: - HashMap是基于哈希表实现的键值对集合,键和值都可以存储任何对象类。 - HashMap的优点是能够快速查找元素,缺点是键和值的顺序是随机的。 - HashMap支持高效的插入、删除和查找操作,但不能保证键和值的顺序。 6. TreeMap: - TreeMap是基于红黑树实现的有序键值对集合,键不能重复,值可以存储任何对象类。 - 红黑树的优点是能够自动排序,插入和删除元素的效率较高,缺点是随机访问元素的效率较低。 - TreeMap支持高效的插入、删除和查找操作,并且按照键的顺序排列。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值