啃掉JDK源码(一):String

系列文章目录

提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加

  1. 第一章 String
  2. 第二章 Integer
  3. 第三章 ArrayList
  4. 第四章 LinkedList
  5. 第五章 HashMap
  6. 第六章 ConcurrentHashMap
  7. 第七章 AbstractQueuedSynchronizer(AQS)
  8. 第八章 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;
}

总结

提示:这里对文章进行总结:

😛😛😛

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小心仔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值