标题:浅谈字符串比较
只看楼主
蓝神100
Rank: 1
等 级:禁止访问
帖 子:18
专家分:0
注 册:2017-2-14
结帖率:40%
已结贴  问题点数:5 回复次数:1 
浅谈字符串比较
浅谈字符串比较
前一段时间自己想写几行代码,所以就有了以下的代码:

public class TestString_1 {
public static void main(String[] args) {
        String str1="this is test";
        String str2="this is test";
        String str3=new String("this is test");
        String str4=new String("this is test");
System.out.println("str1==str2:"+(str1==str2));
    System.out.println("str2==str3:"+(str2==str3));
    System.out.println("str3==str4:"+(str3==str4));
    }
}

运行结果是:

str1==str2:true
str2==str3:false
str3==str4:false

果然和我想的一样。这样就可以了。到时候和学生说str1和str2是同一个HashCode,而str2和str3不是同一个HashCode就可以了。哈哈!心中不由泛起对自己的崇拜。
                 
为了让学生们更加的崇拜我。那就给他们show一下HashCode吧!在原有代码的基础上加了几行输出。(作死开始!)
        System.out.println("str1==>"+str1.hashCode());
        System.out.println("str2==>"+str2.hashCode());
        System.out.println("str3==>"+str3.hashCode());
        System.out.println("str4==>"+str4.hashCode());
可是输出结果却出人意料!!!
str1==>990854726
str2==>990854726
str3==>990854726
str4==>990854726


说好的HashCode不一样呢?说好的HashCode是用优化地址算法的结晶,可是现在总是感觉自己在作梦一样。为什么会这样啊?
好吧,静下心来先解决第一个问题!HashCode是怎么来的。
在这里,我们先不提及其它类。先来说一说String类。它的HashCode是自己覆写了Object的HashCode的方法。这段是从jdk1.7里面找到的源码。

public int hashCode() {
        int h = hash;//hash的值默认为0
        if (h == 0 && count > 0) {//count为当前字符串的长度
 //offset是字符串操作时的下标
            int off = offset;
 //将当前字符串的值分割成字符数组
            char val[] = value;
            int len = count;

            for (int i = 0; i < len; i++) {
                h = 31*h + val[off++];
            }
            hash = h;
        }
        return h;
}

好吧。这段代码内我已经注释了一部份。而最核心的那段for循环却没有解释。这里才是Hash算法的体现之处。这里面的h就是一个哈希值。是用累加上一次的h*31再加上当前字符的编码值而算出来的。

可是什么是HashCode?为什么要有这么一段东西啊?

Hash其实是一种常用的数据结构。它的主要目的是对某组数据快速产生摘要。以方便大量数据之间进行对比。比方说我们常用的HashSet,在存储数据的时候就可能会有这样的需求。HashSet的存储数据的特征之一就是内容不重复。想要完成这样的目的就会存在值的比较。数据量不足时,这种直接用值进行比较的方法还是可行的。但假设set内已经有1000条的情况下。使用 set.add(“hi”);单纯进行值的比较就会有1000次的比较。这样的工作效率很低。使用HashCode就不一样了,比方说HashSet,底层是基于HashMap实现的,先通过HashCode取一个模,这样一下子就固定到某个位置了,如果这个位置上没有元素,那么就可以肯定HashSet中必定没有和新添加的元素equals的元素,就可以直接存放了,都不需要比较;如果这个位置上有元素了,逐一比较,比较的时候先比较HashCode,HashCode都不同接下去都不用比了,肯定不一样,HashCode相等,再equals比较,没有相同的元素就存,有相同的元素就不存。
所以我们知道了什么是HashCode,以及它存在的意义,还有在JAVA里String的Hash算法了。那么我们明白了一个道理。相同的字符串的HashCode一定相等。(因为算法一致嘛)
那么直接用str1.hashCode()去和str2.hashCode()比较不就可以验证两个字符串是否相等了?

我们再回头看看之前的代码。因为代码中的 h 是int类型的。当给出的值足够长的情况下结果很可能会有溢出。那么虽然重复的概率很少,但也一定有不同字符串的HashCode的值相同。
public class TestString_2 {
    public static void main(String[] args) {
        String str1="重地";
        String str2="通话";
        System.out.println("str1==>"+str1.hashCode());
        System.out.println("str2==>"+str2.hashCode());
    }
}
输出结果就是:
str1==>1179395
str2==>1179395

所以才会有equals()方法。下面来看看String的equals()方法的代码
public boolean equals(Object anObject) {
        //比较两个对象是否相同
        if (this == anObject) {
            return true;
        }
        //比较两个对像是字符串类型
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            //下面是将两个对象内的值一一进行比较
            int n = count;
            if (n == anotherString.count) {
               
                char v1[] = value;
                char v2[] = anotherString.value;
               
                int i = offset;
                int j = anotherString.offset;
                while (n-- != 0) {
                    if (v1[i++] != v2[j++])
                        return false;
                }
                return true;
            }
        }
        return false;
    }
通过上面的代码,我们可以了解到。equals()方法有几个步骤。
1判断传入对象的引用是否和当前对象相同,如果相同就直接返回true;
2判断传入对象是否属于String类型,如果不同就直接返回false;
3判断每个值与当前对象的值是否不同,如果不同就返回false;
4如果以上比较都没有查出false那么才会返回true;


关于 == 的使用
==是容易理解的。java设计 == 就是要比较两个对象引用的是不是同一个对象。
    对于引用变量而言,比较的时候两个引用变量引用的是不是同一个对象,即比较的是两个引用中存储的对象地址是不是一样的。
    对于基本数据类型而言,比较的就是两个数据是不是相等,所以没什么歧义。

总结一下吧。
1比较对象的引用(即两个引用是否同时引用同一对象时)用“==”。
2而比较两个对象的值是否相等的时候,还是要使用equals()方法。
3HashCode在String类中只是通过value来给对象作出一个摘要来。方便快速比较的。

虽然为自己开始的无知而感到害羞。但是通过一阵非常努力的折腾,最后我还是有点收获的。心中泛起一丢丢地傲娇。

搜索更多相关主题的帖子: public 字符串 
2017-04-18 14:57
纵横阳仔
Rank: 7Rank: 7Rank: 7
来 自:自学成才的火星人儿
等 级:贵宾
威 望:26
帖 子:147
专家分:698
注 册:2016-10-20
得分:5 
总结的很好,赞一个
2017-04-19 10:55



参与讨论请移步原网站贴子:https://bbs.bccn.net/thread-476223-1-1.html




关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.793816 second(s), 7 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved