链表及数据结构

一、什么是java链表

使用两个 分别指向下一个指针和向前的指针 将节点连接一起来的节点的集合就是链表- -

  • 链表通常在物理存储上是无序的
    在这里插入图片描述
    • 1的位置是当前链表的起始位置,我们称之为表头,它里面放着的是第一个数据的地址(2),而2里面不仅有数据还有p2,p2指向的是第二个数据的位置,第二个数据里面不仅有2,同时里面放着p3,p3指向下一个数据的位置,而4这里最后的指针指向的是NULL,也就是说链表就到这里结束。
    • 就像一条火车,里面的数据就是我们的车厢,而指针就是将数据链接起来的链条,所以我们称之为链表。

二、数据存储结构

数据的存储结构:也称为数据的物理结构,是数据的逻辑结构在计算机中的实现

需要指出的是,数据的逻辑结构是从数据元素之间的逻辑关系来分析数据的,与数据的具体存储无关,是独立于计算机之外的。而数据的存储结构是依赖于计算机的,包括数据元素值在计算机中的存储表示和逻辑关系在计算机中的存储表示

数据元素之间逻辑关系在计算机中的存储表示分为以下四种:

  1. 顺序存储方式:顺序存储方式是指将所有的数据元素放在一段连续的存储空间中,并使逻辑上相邻的数据元素其对应的物理存储位置也是相邻的(即保证逻辑位置关系与物理位置关系的一致)。顺序存储结构通常借助程序设计语言中的数组来加以实现。
  2. 链式存储方式:链式存储方式不需要将逻辑上相邻的元素存储在物理位置相邻的位置,也就是说数据元素的存储具有任意性。每个数据元素所对应的存储表示由两部分组成,一部分存储元素值本身,另一部分用于存放表示逻辑关系的指针。我们可以认为指针给出的是下一个数据元素的存储地址。
  3. 索引存储方式:索引存储方式在存储数据元素的同时还增加了一个索引表。索引表中的每一项包括关键字和地址,关键字是能够唯一标示一个数据元素的数据项,地址是指示数据元素的存储地址或者存储区域的首地址的。
  4. 散列存储方式:散列存储也称为哈希存储,这种存储方式将数据元素存储在一个连续的区域,每一个数据元素的具体存储位置是根据该数据的关键字值,通过散列(哈希)函数直接计算出来的。

三、散列

理解:假如有一个列表,我们将数据放在不同的表格中就是散列。最合理的做法是均匀的进行分布。比如有一个列表有10个单元格,同时有10个字符串,那么我们最合理的做法是把这10个字符串分配到这10个单元格,不合理的做法就是把这10个数塞到同一个单元格

散列算法: 我们分配这10个字符串的方式,比如取余,比如除以1,除以自身等等
hash:一种散列算法(时间上我们通常说散列就是hash,hash就是散列),一种可以根据对象大小、长度、内容等等因素计算出数值的算法。计算的结果可以看做是内存的地址。经过hash计算后每个对象会被合理的散列到内存中。所以java中的hashcode可以被看做是内存的地地址

四、 hashCode

  • 如果两个对象相同, equals方法一定返回true,并且这两个对象的HashCode一定相同;
  • 两个对象的HashCode相同,并不一定表示两个对象就相同,即equals()不一定为true,只能说明这两个对象在一个散列存储结构中。
  • 如果对象的equals方法被重写,那么对象的HashCode也尽量重写
  • d)HashCode的作用:
    • Java中的集合有两类,一类是List,再有一类是Set。前者集合内的元素是有序的,元素可以重复;后者元素无序,但元素不可重复。 equals方法可用于保证元素不重复,但如果每增加一个元素就检查一次,若集合中现在已经有1000个元素,那么第1001个元素加入集合时,就要调用1000次equals方法。这显然会大大降低效率。 于是,Java采用了哈希表的原理。
    • 哈希算法也称为散列算法,是将数据依特定算法直接指定到一个地址上。这样一来,当集合要添加新的元素时,先调用这个元素的HashCode方法,就一下子能定位到它应该放置的物理位置上。
        1. 如果这个位置上没有元素,它就可以直接存储在这个位置上,不用再进行任何比较了
        1. 如果这个位置上已经有元素了,就调用它的equals方法与新元素进行比较,相同的话就不存了
        1. 不相同的话,也就是发生了Hash key相同导致冲突的情况,那么就在这个Hash key的地方产生一个链表,将所有产生相同HashCode的对象放到这个单链表上去,串在一起。这样一来实际调用equals方法的次数就大大降低了,几乎只需要一两次
HashCode的作用:

从Object角度看,JVM每new一个Object,它都会将这个Object丢到一个Hash表中去,这样的话,下次做Object的比较或者取这个对象的时候(读取过程),它会根据对象的HashCode再从Hash表中取这个对象。这样做的目的是提高取对象的效率。若HashCode相同再去调用equals。

五、equals()与hashCode()的联系

Java的超类Object类已经定义了equals()和hashCode()方法,在Obeject类中,equals()比较的是两个对象的内存地址是否相等,而hashCode()返回的是对象的内存地址。所以hashCode主要是用于查找使用的,而equals()是用于比较两个对象是否相等的。但有时候我们根据特定的需求,可能要重写这两个方法,在重写这两个方法的时候,主要注意保持一下几个特性:

  • 如果两个对象的equals()结果为true,那么这两个对象的hashCode一定相同
  • 两个对象的hashCode()结果相同,并不能代表两个对象的equals()一定为true,只能够说明这两个对象在一个散列存储结构中
  • 如果对象的equals()被重写,那么对象的hashCode()也要重写

六、基本数据类型和String类型的hashCode()方法和equals()方法

  • hashCode():八种基本类型的hashCode()很简单就是直接返回他们的数值大小,String对象是通过一个复杂的计算方式,但是这种计算方式能够保证,如果这个字符串的值相等的话,他们的hashCode就是相等的
  • equals():8种基本类型的封装类的equals方法就是直接比较数值,String类型的equals方法是比较字符串的值的

七、java.lang.Object 的对 hashCode() 方法有三项约定

  • 第一,当一个对象 equals() 方法所使用的字段不变时,多次调用 hashCode() 方法的值应保持不变
  • 第二,如果两个对象 equals(Object o) 方法是相等的,则 hashCode() 方法值必须相等
  • 第三,如果两个对象 equals(Object o) 方法是不相等,则 hashCode() 方法值不要求相等,但在这种情况下尽量确保 hashCode 不同,以提升性能

八、 将一个对象转变为hashCode过程

对象–>物理地址–>hash()函数—>hashCode码值(一般为整数)代表了物理地址在hash表中的位置
所以hashCode和hash表的作用主要是为了查找方便,能快速的定位位置。Hashcode并不是物理地址,比如两个筒存放地址,hashcode只是代表他存在哪个筒中

参考转载: https://blog.csdn.net/weixin_44364444/article/details/120054230

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值