Equals和EqualsIgnoreCase源码分析

Equals和EqualsIgnoreCase源码分析

先看下模拟案例

package csdn.hsy.cool.blog;

/**
 * 源码分析练习:简单篇之字符串比较Equals和EqualsIgnoreCase方法
 * 2020/08/20
 */
public class EqualsAndEqualsIgnoreCase {
    public static void main(String[] args) {
        //模拟构造一个字符串数组,尽可能模拟各种条件
        String str="qwer";  //str为作比较的字符串
        String str1="qwer";
        String str2="QWER";
        String str3="QwER";
        String str4="qWEr";
        String ssjjkk="qwerJJJ";
        String ssjjLL="qe";
        String ssjjMM="45rqwradgag";
        String []list={str1,str2,str3,str4,ssjjkk,ssjjLL,ssjjMM};
        //模拟equals方法,完全相同比较
        System.out.println("======模拟equals方法,完全相同比较======");
        for(int i=0;i<list.length;i++){
            System.out.println(list[i]+"与"+str+"是否完全相等?           result="+list[i].equals(str));
        }
        //模拟equalsIgnoreCase方法,忽略大小写比较
        System.out.println("======模拟equalsIgnoreCase方法,忽略大小写比较======");
        for(int i=0;i<list.length;i++){
            System.out.println(list[i]+"与"+str+"是否完全相等?           result="+list[i].equalsIgnoreCase(str));
        }
    }


}

结果:

======模拟equals方法,完全相同比较======
qwer与qwer是否完全相等?           result=true
QWER与qwer是否完全相等?           result=false
QwER与qwer是否完全相等?           result=false
qWEr与qwer是否完全相等?           result=false
qwerJJJ与qwer是否完全相等?           result=false
qe与qwer是否完全相等?           result=false
45rqwradgag与qwer是否完全相等?           result=false
======模拟equalsIgnoreCase方法,忽略大小写比较======
qwer与qwer是否完全相等?           result=true
QWER与qwer是否完全相等?           result=true
QwER与qwer是否完全相等?           result=true
qWEr与qwer是否完全相等?           result=true
qwerJJJ与qwer是否完全相等?           result=false
qe与qwer是否完全相等?           result=false
45rqwradgag与qwer是否完全相等?           result=false

可以看到这结果和我们这两个函数的含义没有差别,完全相同比较和忽略大小写比较,下面看一下源码,先看复杂的equalsIgnoreCase,然后equals就一笔带过了。

跟踪一下equalsIgnoreCase方法

    public boolean equalsIgnoreCase(String anotherString) {
        return (this == anotherString) ? true
                : (anotherString != null)
                && (anotherString.value.length == value.length)
                && regionMatches(true, 0, anotherString, 0, value.length);
    }

首先要知道调用此方法的形式是: str.equalsIgnoreCase(“xxxxx”)

总体 return 是 条件1&&条件2&&条件3,其中条件1是三目运算。

那么,此处就比较好理解了。

首先判断条件1:判断2个字符串是否相同?如果相同,返回true,如果不同,看要比较的xxxx是否不为空,为空返回false,不为空返回true,继续执行后面的逻辑,这一块是三目运算。

如果条件1成立,判断条件2,判断2个字符串的长度是否相同,如果相同,返回true,去看条件3,如果不相同,返回false。

如果条件2成立,判断条件3,条件3是个方法,返回这个方法的结果。下面分析一下这个方法的作用,我们知道equalsIgnoreCase是忽略大小写来判断的,至今没有看到相关的代码,所以,大胆猜测一下,相关当面很有可能就在regionMatches方法中,下面分析一下。

public boolean regionMatches(boolean ignoreCase, int toffset,
            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;
    }

首先说一下我对方法这几个参数的理解:

public boolean regionMatches(boolean ignoreCase, int toffset,
            String other, int ooffset, int len)
boolean ignoreCase:传入一个true/false标识,用来控制方法的执行
int toffset:传入this(此处示例代码的str,qwer)转为字符数组的初始下标,用于后续比较
String other:传入要比较的字符串
int ooffset:传入要比较字符串(此处示例代码中的str1,str2等)转为字符数组的初始下标,用于后续比较
int len:传入this字符串的长度,用于确定循环的次数
==================================================================
//前提:
字符串的比较核心是字符的比较,将字符串转为字符数组,逐个字符比较

知道了上述所说的之后,regionMatches方法就很好理解了。

        char ta[] = value;
        int to = toffset;
        char pa[] = other.value;
        int po = ooffset;

要比较的2个字符串转为字符数组

        if ((ooffset < 0) || (toffset < 0)
                || (toffset > (long)value.length - len)
                || (ooffset > (long)other.value.length - len)) {
            return false;
        }

这一块没看出来具体的好处或者作用,因为看调用出传入的都是0,而且前置为3个条件&&,其实如果长度不相同的话,就走不到第3个条件了,也就走不到这里,所以感觉这种情况不存在,不知道源码为何写一个这个,可能是出于我没考虑到的情况还是历史遗留代码,没有删除。下面就是前置条件,以上是我个人的思考。如果读者知道,请在评论区及时留言。

return (this == anotherString) ? true
                : (anotherString != null)
                && (anotherString.value.length == value.length)
                && regionMatches(true, 0, anotherString, 0, value.length);
   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;
        }

这一块就比较好理解了,全转大写/小写比较。上面就是忽略大小写比较方法的源码分析,个人理解,有问题及时指出。下面看一下全选相同方法源码。

    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;
    }

之所以把它放在后面分析,是因为比较简单,留给读者吧,相信有了上面的分析,这个应该不难理解。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值