系列文章目录
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
- 第一章 String
- 第二章 Integer
- 第三章 ArrayList
- 第四章 LinkedList
- 第五章 HashMap
- 第六章 ConcurrentHashMap
- 第七章 AbstractQueuedSynchronizer(AQS)
- 第八章 ReentrantLock
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
提示:这里可以添加本文要记录的大概内容:
最近这段时间,准备开始JDK源码系列的学习,在这里记下自己学习的成果!😃😃😃
String类(JDK1.8)是我们开发中使用最多的一个类,对以下几个方法进行分析:
- equals
- hashCode
- equalsIgnoreCase
- indexOf
- startsWith
- concat
- substring
- split
- trim
- compareTo
不对的地方请多多指教!😢😢😢
提示:以下是本篇文章正文内容,下面案例可供参考
一、源码剖析
首先看String类实现接口
public final class String
implements java.io.Serializable, Comparable<String>, CharSequence {
-
java.io.Serializable
这个序列化接口没有任何方法和域,仅用于标识序列化的语意。 -
Comparable
这个接口只有一个compareTo(T 0)接口,用于对两个实例化对象比较大小。 -
CharSequence
这个接口是一个只读的字符序列。包括length(), charAt(int index), subSequence(int start, int end)这几个API接口,值得一提的是,StringBuffer和StringBuild也是实现了该接口。
变量:
// value 用于存储字符串,String str = "a"; 本质存入 char类型数组中。final修饰,不能指向其他的数组,但内容可变。不可变是因为提供的 API,返回一个新的 String对象。
private final char value[];
// String 实例化的 hashcode的一个缓存。String 经常用来比较,比如HashMap,每次都重新计算hashcode,就会比较浪费时间,保存一个hashcode的缓存来进行优化
private int hash; // Default to 0
二、方法介绍
equals
equals() 方法用于判断 Number 对象与方法的参数进是否相等
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) { // 比较char数组
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
hashCode
根据官方文档的定义:Object.hashCode() 函数用于这个函数用于将一个对象转换为其十六进制的地址。
如果2个对象相同,则其hash码也应该相同。一般重写eauals方法,那么hashcode方法就需要重写
/**
* Returns a hash code for this string. The hash code for a
* {@code String} object is computed as
* <blockquote><pre>
*
* s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]
*
* </pre></blockquote>
* using {@code int} arithmetic, where {@code s[i]} is the
* <i>i</i>th character of the string, {@code n} is the length of
* the string, and {@code ^} indicates exponentiation.
* (The hash value of the empty string is zero.)
*
* @return a hash code value for this object.
*/
public int hashCode() {
int h = hash;
if (h == 0 && value.length > 0) { // 哈希值不为0直接返回
char val[] = value;
for (int i = 0; i < value.length; i++) {
h = 31 * h + val[i]; // 计算哈希值
}
hash = h; // 哈希值保存
}
return h;
}
计算方法
String str = "abc";
System.out.println("hashcode值为:" + str.hashCode()); // 96354
// 31*0 + a = 97
// 31*97 + b = 3105
// 31*3105 + c = 96354
equalsIgnoreCase
equalsIgnoreCase() 方法用于将字符串与指定的对象比较,不考虑大小写
// 源码实现
public boolean equalsIgnoreCase(String anotherString) {
return (this == anotherString) ? true // 检查是否同一个对象
: (anotherString != null)
&& (anotherString.value.length == value.length) // 长度是否相等
&& regionMatches(true, 0, anotherString, 0, value.length);
}
// 核心方法
public boolean regionMatches(boolean ignoreCase, int toffset, // ignoreCase:是否忽略大小写 other:比较字符串 len:字符串长度
String other, int ooffset, int len) {
char ta[] = value;
int to = toffset;
char pa[] = other.value;
int po = ooffset;
// Note: toffset, ooffset, or len might be near -1>>>1.
if ((ooffset < 0) || (toffset < 0) // 参数校验
|| (toffset > (long)value.length - len)
|| (ooffset > (long)other.value.length - len)) {
return false;
}
while (len-- > 0) { // 遍历两个字符串进行比较
char c1 = ta[to++];
char c2 = pa[po++];
if (c1 == c2) {
continue;
}
if (ignoreCase) {
// If characters don't match but case may be ignored,
// try converting both characters to uppercase.
// If the results match, then the comparison scan should
// continue.
char u1 = Character.toUpperCase(c1); // 转换大写进行判断是否相等
char u2 = Character.toUpperCase(c2);
if (u1 == u2) {
continue;
}
// Unfortunately, conversion to uppercase does not work properly
// for the Georgian alphabet, which has strange rules about case
// conversion. So we need to make one last check before
// exiting.
if (Character.toLowerCase(u1) == Character.toLowerCase(u2)) { // 某些特殊字符不支持大写,这里转换成小写在进行比较
continue;
}
}
return false;
}
return true;
}
indexOf
查找指定字符或字符串在字符串中第一次出现地方的索引,未找到的情况返回 -1
static int indexOf(char[] source, int sourceOffset, int sourceCount,
char[] target, int targetOffset, int targetCount,
int fromIndex) {
if (fromIndex >= sourceCount) {
return (targetCount == 0 ? sourceCount : -1);
}
if (fromIndex < 0) {
fromIndex = 0;
}
if (targetCount == 0) {
return fromIndex;
}
char first = target[targetOffset]; // 搜索的第一个字符
int max = sourceOffset + (sourceCount - targetCount);
for (int i = sourceOffset + fromIndex; i <= max; i++) {
/* Look for first character. */
if (source[i] != first) {
while (++i <= max && source[i] != first);
}
/* Found first character, now look at the rest of v2 */
if (i <= max) {
int j = i + 1;
int end = j + targetCount - 1;
for (int k = targetOffset + 1; j < end && source[j]
== target[k]; j++, k++);
if (j == end) {
/* Found whole string. */
return i - sourceOffset;
}
}
}
return -1;
}
总结
提示:这里对文章进行总结:
😛😛😛