闲扯hash,string

1.数组查询为何比链表快?

 

1.寻址次数链表要多一些。数组只需对基地址+元素大小*k就能找到第k个元素的地址 对其取地址就能获得该元素。链表要获得第k个元素,首先要在其第k-1个元素寻找到其next指针偏移,再将next指针作为地址获得值。多了一步寻址操作,当数据量大且其它操作较少时 这就有差距了

2.CPU缓存会把一片连续的内存空间读入,因为数组结构是连续的内存地址,所以数组全部或者部分元素被连续存在CPU缓存里面,平均读取每个元素的时间只要3CPU时钟周期。   而链表的节点是分散在堆空间里面的,这时候CPU缓存帮不上忙,只能是去读取内存,平均读取时间需要100CPU时钟周期。这样算下来,数组访问的速度比链表快33倍! (这里只是介绍概念,具体的数字因CPU而异)。

 

哈希(散列结构):

散列结构有什么好处?解决了什么问题?

优点:

哈希表使用hash function来对输入的数据分配index到哈希表对应的槽中。假设有一个哈希表的size100,而我们输入的数据是从099,我们要把输入数据储存到哈希表中。理论上来说,该哈希表插入和查找操作的时间复杂度都是O(1)

缺点:

  1. 当更多的数插入时,哈希表冲突的可能性就更大。对于冲突,哈希表通常有两种解决方案:第一种是线性探索,相当于在冲突的槽后建立一个单链表,这种情况下,插入和查找以及删除操作消耗的时间会达到O(n),且该哈希表需要更多的空间进行储存。第二种方法是开放寻址,他不需要更多的空间,但是在最坏的情况下(例如所有输入数据都被map到了一个index上)的时间复杂度也会达到O(n)
  2. 所以,在决定建立哈希表之前,最好可以估计输入的数据的size。否则,resize哈希表的过程将会是一个非常消耗时间的过程。例如,如果现在你的哈希表的长度是100,但是现在有第101个数要插入。这时,不仅哈希表的长度可能要扩展到150,且扩展之后所有的数都需要重新rehash
  3. 哈希表中的元素是没有被排序的。然而,有些情况下,我们希望储存的数据是有序的。

 

  1. JdkString的哈希算法 public int hashCode() {
  2.     int h = hash;
  3.     //hash default value : 0
  4.     if (h == 0 && value.length > 0) {
  5.         //value : char storage
  6.         char val[] = value;
  7.         for (int i = 0; i < value.length; i++) {
  8.             h = 31 * h + val[i];
  9.         }
  10.         hash = h;
  11.     }
  12.     return h;
  13. }

很简洁的一个乘加迭代运算,在不少的hash算法中,使用的是异或+加法进行迭代,速度和前者差不多。

2Hash在在密码学中的应用

3 String字符串解析

  1. string的结构

为什么string要实现序列化,要定义private static final ObjectStreamField[] serialPersistentFields =

        new ObjectStreamField[0];

这个类的作用是创建具有指定类型的序列化对象。

这个字段?

目前怀疑是把char value[]这个字段给序列化了,打印的时候是对char的反序列化过程

 

 

 

private final char value[];

 

    /** Cache the hash code for the string */

    private int hash; // Default to 0

 

    /** use serialVersionUID from JDK 1.0.2 for interoperability */

    private static final long serialVersionUID = -6849794470754667710L;

 

    /**

     * Class String is special cased within the Serialization Stream Protocol.

     *

     * A String instance is written into an ObjectOutputStream according to

     * <a href="{@docRoot}/../platform/serialization/spec/output.html">

     * Object Serialization Specification, Section 6.2, "Stream Elements"</a>

     */

    private static final ObjectStreamField[] serialPersistentFields =

        new ObjectStreamField[0];

 

    /**

     * Initializes a newly created {@code String} object so that it represents

     * an empty character sequence.  Note that use of this constructor is

     * unnecessary since Strings are immutable.

     */

    public String() {

        this.value = "".value;

    }

 

String的equals方法:比较string内char数组的值是否不等

public boolean equals(Object anObject) {

        if (this == anObject) {

            return true;

        }

        if (anObject instanceof String) {

            String anotherString = (String)anObject;

            int n = value.length;

            if (n == anotherString.value.length) {

                char v1[] = value;

                char v2[] = anotherString.value;

                int i = 0;

                while (n-- != 0) {

                    if (v1[i] != v2[i])

                        return false;

                    i++;

                }

                return true;

            }

        }

        return false;

}

 

/**

     * 这个是什么意思呢》返回一个string对象本身?

为什么这样返回就不打印哈希值而是直接打印字符?

     *

     * @return  the string itself.

     */

    public String toString() {

        return this;

}

 

打印对象的引用时,会默认调用Object类的toString()方法,返回的是一个字符串表示,该字符串的形式为类名+@+十六进制的哈希值;为什么String打印的不是这样一个地址值呢?因为String类继承自Object类,重写了从Object类拿到的toString()方法,返回的是该该对象本身,即字符串。

 

 

API中Object类的toString()方法:

 

public String toString()

返回该对象的字符串表示。通常,toString 方法会返回一个“以文本方式表示”此对象的字符串。结果应是一个简明但易于读懂的信息表达式。建议所有子类都重写此方法。

Object 类的 toString 方法返回一个字符串:

  public String toString() {

                return getClass().getName() + "@" + Integer.toHexString(hashCode());

    }

 

public native int hashCode();

  1. 为什么需要hashcode

Stringhashcode为什么是质数:

首先来说假如关键字是随机分布的,那么无所谓一定要模质数。但在实际中往往关键字有某种规律,例如大量的等差数列,那么公差和模数不互质的时候发生碰撞的概率会变大,而用质数就可以很大程度上回避这个问题。

质数并不是唯一的准则,具体可以参考以下网站。

 

   public boolean equals(Object anObject) {

        if (this == anObject) {

            return true;

        }

        if (anObject instanceof String) {

            String anotherString = (String)anObject;

            int n = value.length;

            if (n == anotherString.value.length) {

                char v1[] = value;

                char v2[] = anotherString.value;

                int i = 0;

                while (n-- != 0) {

                    if (v1[i] != v2[i])

                        return false;

                    i++;

                }

                return true;

            }

        }

        return false;

    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值