如何比较两个字符串是否一样 您所在的位置:网站首页 怎么比较两个字符串是否一样C语言 如何比较两个字符串是否一样

如何比较两个字符串是否一样

#如何比较两个字符串是否一样| 来源: 网络整理| 查看: 265

看似简单的问题,可以引申为操作符==和equals()方法有什么区别?

==操作符用于比较两个对象的地址是否相等equals()用于比较两个对象的内容是否相等 // String对象比较 String alita=new String("小萝莉"); String luolita=new String("小萝莉"); System.out.println(alita.equals(luolita)); // true System.out.println(alita == luolita); // false

.equals() 输出的结果为 true,而“==”操作符输出的结果为 false 前者要求内容相等就可以,后者要求必须是同一个对象。

Java 的所有类都默认地继承 Object 这个超类,该类有一个名为 .equals() 的方法。

Object的源码 public boolean equals(Object obj) { return (this == obj); }

Object 类的 .equals() 方法默认采用的是“==”操作符进行比较。 假如子类没有重写该方法的话,那么“==”操作符和 .equals() 方法的功效就完全一样——比较两个对象的内存地址是否相等。

equals()源码 public boolean equals(Object anObject) { if (this == anObject) { return true; } if (anObject instanceof String) { String aString = (String)anObject; if (coder() == aString.coder()) { return isLatin1() ? StringLatin1.equals(value, aString.value) : StringUTF16.equals(value, aString.value); } } return false; }

首先,如果两个字符串对象的可以“==”,那就直接返回 true 了,因为这种情况下,字符串内容是必然相等的。否则就按照字符编码进行比较,分为 UTF16 和 Latin1,差别不是很大,就拿 Latin1 的来说吧。

public static boolean equals(byte[] value, byte[] other) { if (value.length == other.length) { for (int i = 0; i return false; } } return true; } return false; }

我的 JDK 版本是 Java 11,也就是最新的 LTS(长期支持)版本。该版本中,String 类使用字节数组实现的,所以比较两个字符串的内容是否相等时,可以先比较字节数组的长度是否相等,不相等就直接返回 false;否则就遍历两个字符串的字节数组,只要有一个字节不相等,就返回 false。

第一题:

new String("小萝莉").equals("小萝莉")

.equals() 比较的是两个字符串对象的内容是否相等,所以结果为 true。

第二题:

new String("小萝莉") == "小萝莉"

==操作符左侧的是在堆中创建的对象,右侧是在字符串常量池中的对象,尽管内容相同,但内存地址不同,所以返回 false。

第三题:

new String("小萝莉") == new String("小萝莉")

new 出来的对象肯定是完全不同的内存地址,所以返回 false。

第四题:

"小萝莉" == "小萝莉"

字符串常量池中只会有一个相同内容的对象,所以返回 true

第五题:

"小萝莉" == "小" + "萝莉"

由于‘小’和‘萝莉’都在字符串常量池,所以编译器在遇到‘+’操作符的时候将其自动优化为“小萝莉”,所以返回 true。

第六题:

new String("小萝莉").intern() == "小萝莉"

new String(“小萝莉”) 在执行的时候,会先在字符串常量池中创建对象,然后再在堆中创建对象;执行 intern() 方法的时候发现字符串常量池中已经有了‘小萝莉’这个对象,所以就直接返回字符串常量池中的对象引用了,那再与字符串常量池中的‘小萝莉’比较,当然会返回 true

如果要进行两个字符串对象的内容比较,除了 .equals() 方法,还有其他两个可选的方案。

1)Objects.equals()

Objects.equals() 这个静态方法的优势在于不需要在调用之前判空。

public static boolean equals(Object a, Object b) { return (a == b) || (a != null && a.equals(b)); }

如果直接使用 a.equals(b),则需要在调用之前对 a 进行判空,否则可能会抛出空指针 java.lang.NullPointerException。

Objects.equals("小萝莉", new String("小" + "萝莉")) // --> true Objects.equals(null, new String("小" + "萝莉")); // --> false Objects.equals(null, null) // --> true String a = null; a.equals(new String("小" + "萝莉")); // throw exception 2)String 类的 .contentEquals()

.contentEquals() 的优势在于可以将字符串与任何的字符序列(StringBuffer、StringBuilder、String、CharSequence)进行比较。

public boolean contentEquals(CharSequence cs) { // Argument is a StringBuffer, StringBuilder if (cs instanceof AbstractStringBuilder) { if (cs instanceof StringBuffer) { synchronized(cs) { return nonSyncContentEquals((AbstractStringBuilder)cs); } } else { return nonSyncContentEquals((AbstractStringBuilder)cs); } } // Argument is a String if (cs instanceof String) { return equals(cs); } // Argument is a generic CharSequence int n = cs.length(); if (n != length()) { return false; } byte[] val = this.value; if (isLatin1()) { for (int i = 0; i return false; } } } else { if (!StringUTF16.contentEquals(val, cs, n)) { return false; } } return true; }

从源码上可以看得出,如果 cs 是 StringBuffer,该方法还会进行同步,非常的智能化;如果是 String 的话,其实调用的还是 equals() 方法。

自定义对象的比较

上面比较的String是系统自带的,下面我们来看看如果是自己定义类,使用equals还可以吗?

package com.study; import java.util.Objects; /** * @Description TODO * @Classname Person * @Date 2021/8/22 14:45 * @Created by 折腾的小飞 */ public class Person { private String name; // 名字 private int age; // 年龄 // 无参构造 public Person() { } // 有参构造 public Person(String name, int age) { this.name = name; this.age = age; } // get方法和set方法,用来得到和设置成员变量的值 public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } // toString方法,用来打印 @Override public String toString() { return "Person{" + "name='" + name + '\'' + ", age=" + age + '}'; } } // 自定义对象的比较 Person p1 = new Person("卓卓", 22); Person p2 = new Person("卓卓", 22); System.out.println(p1 == p2); // faslse System.out.println(p1.equals(p2)); //false

怎么回事呢? 怎么使用了equals比较还是false呢?

ctrl+鼠标左键点击进去发现

public boolean equals(Object obj) { return (this == obj); }

当是同一个对象时,返回true;不是一个对象,返回false。 我们发现它还是比较的地址,怎么办呢? 我们需要重写equals()方法,让它去比较对象的内容 重写了的equals()方法如下:

@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Person person = (Person) o; return age == person.age && Objects.equals(name, person.name); }

第一个,判断,是否为同一个对象 第二个,判断传入的对象是否为空,类名是否相等 第三个,判断属性值是否相等

还有一个hashCode()方法,用于比较对象的hash值是否相同

System.out.println(p1.hashCode()); System.out.println(p2.hashCode());

在这里插入图片描述 发现两个对象的内容相同,地址不同。 如果我们要比较内容的hashCode值呢?

我们也可以重写hashCode()方法,去比较对象内容的hash值

@Override public int hashCode() { return Objects.hash(name, age); }

所以,比较自定义对象时,需要重写equals()和hashCode()方法



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有