java中Set接口 、HashSet、LinkedHashSet————————————墨白

Set接口概述

我们下面来学习Collection接口的另一个最重要的子类接口————Set接口。Set接口与List接口最大的不同在于,实现Set接口的类(HashSet,TreeSet)等都是没有下标的。也就是不能用以前我们常用的for遍历,必须用迭代器或者增强for遍历(建议用迭代器,灵活)。最有意思的是,我们java中的Set模仿了数学中Set的概念,数学中Set是什么,就是集合啊,数学中集合最重要的特性之一就是集合内元素不能重复,所以我们java中的实现Set接口的实现类也不能有重复元素,其实我们之前就区分过实现List接口的集合和实现Set接口的集合的区别,主要的两个就是(List有下标而且可以重复,Set没下标而且不能重复(其实这个不能重复的意思并不是不能存储重复的元素,而是存储了也没用,输出的时候只有一个))
下面我们先从实现Set接口的HashSet实现类开始讲起。

HashSet类

HashSet接口的底层的是一个哈希表结构,对于哈希表,我们目前只需要知道它的查询速度非常的快。当然,记住了,所有Collection后代都是在java.util包里面,我们先来看一段有意思的代码

import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
public class Main{
    public static void main(String[] args){
        Set<String> mySet=new HashSet<String>();
        mySet.add("小龙女");
        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("尹志平");
        
        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("尹志平");

        Iterator<String> it=mySet.iterator();
        while(it.hasNext()){
            System.out.println(it.next()+"爱"+it.next());

        }
    }
}

在这里插入图片描述
然后这样改代码

public class Main{
    public static void main(String[] args){
        Set<String> mySet=new HashSet<String>();

        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("尹志平");

        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("小龙女");
        Iterator<String> it=mySet.iterator();
        while(it.hasNext()){
            System.out.println(it.next()+"爱"+it.next());

        }
    }
}

运行结果还是:
在这里插入图片描述
然后这样改代码

import java.util.Set;
import java.util.HashSet;
import java.util.Iterator;
public class Main{
    public static void main(String[] args){
        Set<String> mySet=new HashSet<String>();

        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("小龙女");
        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("尹志平");
       
        Iterator<String> it=mySet.iterator();
        while(it.hasNext()){
            System.out.println(it.next()+"爱"+it.next());

        }
    }
}

然后结果还是:
在这里插入图片描述
这就告诉我们两件事
1.Set接口的实现类确实是存储时不重复,哪怕很多次add,只要值一样,那么只存储一次。
2.Set接口遍历是的顺序与存储顺序无关,我们看到了,不管我们怎么改变小龙女与尹志平的存储先后,结果都是尹志平爱小龙女.

哈希值

在继续往下学习之前我们必须引入一个哈希值的概念。所谓哈希值,实质上就是对象的逻辑地址。
我们都知道,一个对象都有物理地址,而他的索引存储的就是这个物理地址。而且使用System.out.println(对象索引);就可以吧索引中的物理地址打印出来,但有的对象直接打印对象索引又不是物理地址,这究竟是为什么呢?
其实都是因为,Object类作为所有对象的祖宗类,他有两个重要的与地址相关方法,一个叫toString()
一个叫hashCode(),这两个函数,第一个是返回物理地址的值,第二个是返回逻辑地址的值(哈希值),打印索引之所以会打印出物理地址,其实就是因为默认调用了toString()方法,有的类打印索引不是物理地址(如 ArrayList LinkedList),是因为这个子类重写了toString()方法。

哈希表

学完了哈希值,就要引出哈希表的概念了,学过数据结构的同学知道哈希表的底层有点类似于一个索引数组。实际就是数组+链表(jdk1.8以后有加入了红黑树,链表长度大于8的时候,转成红黑树,查询速度更快!
数组用来存储哈希值(逻辑地址)
链表用来把哈希值相同的元素串在一起

实现原理如图:
在这里插入图片描述
正是因为这样,哈希表的查询速度非常快,但这也解释了为什么多次存储重复元素只相当于存储了一次,因为Set接口的add重写过,会自动调用hashCode()equals().
这也向我们传达了一个重要的信息!如果我们要用HashSet存储自定义类型元素,那么我们必须重写hashCode()函数和equals()函数。

现在还有一个问题,就是我们刚才插入的元素进入HashSet后都是无顺序的,这就让我们很苦恼,能不能变有序呢?当然能,这就要用到HashSet的子类,LinkedHashSet.

import java.util.LinkedHashSet;
import java.util.Set;
import java.util.Iterator;
public class Main{
    public static void main(String[] args){
        Set<String> mySet=new LinkedHashSet<String>();
        mySet.add("小龙女");
        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("尹志平");

        mySet.add("尹志平");
        mySet.add("尹志平");
        mySet.add("尹志平");

        Iterator<String> it=mySet.iterator();
        while(it.hasNext()){
            System.out.println(it.next()+"爱"+it.next());

        }
    }
}

在这里插入图片描述
这样就有序啦!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值