前一段时间自己想写几行代码,作为学院课件的准备。所以就有了以下的代码:
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来给对象作出一个摘要来。方便快速比较的。
虽然为自己开始的无知而感到害羞。但是通过一阵非常努力的折腾,最后我还是有点收获的。心中泛起一丢丢地傲娇。
分享到:
相关推荐
3. **字符串比较**:介绍equals()、compareTo()和hashCode()等方法的使用,以及字符串的相等性和排序规则。 4. **字符串与字符数组**:阐述字符串与char数组之间的转换,以及它们在内存中的表示。 5. **字符串常量池...
字符串比较是另一个关键点,`equals()`方法用于比较字符串内容是否相等,注意与`==`的区别,后者比较的是对象的引用。`compareTo()`和`compareToIgnoreCase()`可以按照字典顺序比较字符串。 总的来说,Java字符串...
"C语言字符串格式化详解" C语言字符串格式化是指使用printf、scanf等函数对字符串进行格式化处理的技术。字符串格式化是C语言编程中非常重要的一部分,正确地使用字符串格式化可以提高代码的可读性和可维护性。 在...
`expr` 是一个用于执行算术、比较和字符串操作的命令。对于字符串长度的计算,可以使用 `${#string}` 或 `expr length $string`。当字符串包含空格时,需要用双引号括起来。`expr` 的索引命令如 `expr index $...
在Python编程语言中,字符串是数据类型之一,用于存储文本信息。本文将深入探讨字符串的分片与索引以及常用的一些字符串方法。 首先,我们来看字符串的分片和索引。在Python中,通过索引我们可以访问字符串中的单个...
此外,对于字符串的比较,`==`检查的是两个对象是否指向同一个内存位置,而`equals()`方法则比较两个字符串的内容是否相等。如果两个`String`对象包含相同的字符序列,即使它们不是同一个实例,`equals()`也会返回`...
在Java编程语言中,字符串(String)、字符数组(char[])和列表(List)是三种常见的数据结构,它们之间可以通过不同的方法进行相互转换。本文将深入探讨如何在这些数据类型间进行转换,以便更好地理解和应用。 1....
浅谈java字符串比较到底应该用==还是equals Java 中的字符串比较是一个非常重要的主题,在实际项目中,正确地比较字符串是非常关键的。在 Java 中,有两种方式来比较字符串,一种是使用 "==" 运算符,另一种是使用 ...
在处理Web开发中的字符串拼接任务时,我们经常需要将多个字符串片段合并为一个完整的字符串。在JavaScript中,原生的字符串拼接方式,尤其是使用加号(+)操作符,常常会导致性能问题,尤其是在循环中拼接大量字符串...
Java 中字符串数组、字符串、整形之间的转换 在 Java 编程中,字符串数组、字符串、整形之间的转换是非常重要的操作。今天,我们将详细介绍这些转换的实现方法。 字符串数组转字符串 在 Java 中,将字符串数组...
学习python字符串方法的使用,对书中列举的每种方法都做一个试用,将结果记录,方便以后查询。 (1) s.capitalize() ;功能:返回字符串的的副本,并将首字母大写。使用如下: >>> s = 'wwwwww' >>> scap = s....
Java的小论文浅谈String类,讨论了Java中字符串的存储和处理。Java提供了String类、StringBuffer类和StringTokenizer类来存储和处理字符串。在大多数情况下,可以使用String类来创建字符串。 String类在存储和处理...
ES6 模板字符串是JavaScript语言的一个重要更新,它提供了一种更加方便和灵活的方式来创建和操作字符串。模板字符串以反引号(`)包裹,允许我们在字符串中直接嵌入变量和表达式,大大简化了字符串拼接的操作。 在...
### JavaScript 转换日期字符串为 Date 日期对象的方法 在 JavaScript 开发中,处理日期是非常常见的需求之一。很多时候,我们需要将用户输入或其他来源得到的日期字符串转换为 `Date` 对象,以便进行进一步的计算...
在JavaScript中会经常遇到字符串拼接,但是如果要拼接的字符串过长就比较麻烦了。 如果在一行的话,可读性太差;如果换行的话,会直接报错。 现在就来介绍几个JavaScript拼接字符串的几个小技巧(主要针对字符串过长...
总结来说,`MyStringUtils`是一个实用的工具类,它简化了在Java中字符串与集合之间的转换操作,包括将字符串解析为有序无重复的集合、将集合转换回字符串、解析查询字符串为键值对的映射以及比较两个集合是否相等。...
在JavaScript中,数字和字符串之间的转化是常见的操作,特别是在处理用户输入或动态计算时。本文主要探讨了在JS中如何将字符串转化为数字以及数字转化为字符串的方法。 首先,我们来看字符串转数字的几种方法: 1....
在JavaScript中,字符串对象是一个非常基础且重要的概念,它们用于表示一串字符序列。这篇文章主要探讨了在JavaScript中如何处理字符串对象,包括对参数的处理以及字符串对象的属性和方法。 首先,我们来看一下如何...