Как работает equals для строк java
Перейти к содержимому

Как работает equals для строк java

  • автор:

Как работает equals java

Метод equals() в Java используется для проверки равенства двух объектов. Он наследуется из класса Object и может быть переопределен в пользовательских классах.

Метод equals() проверяет, являются ли два объекта равными. По умолчанию метод equals() сравнивает два объекта по ссылке, то есть возвращает true только в том случае, если ссылки указывают на один и тот же объект.

Чтобы сравнить объекты на основе их значений, необходимо переопределить метод equals() в пользовательском классе. При переопределении метода equals() необходимо учитывать следующие рекомендации:

  • Сравнивать переданный объект с текущим объектом через оператор == и вернуть true , если ссылки указывают на один и тот же объект.
  • Проверить, является ли переданный объект null , и вернуть false , если переданный объект равен null
  • Проверить, является ли класс переданного объекта таким же классом, как и текущий объект, используя оператор instanceof
  • Привести переданный объект к типу текущего класса и сравнить поля текущего объекта с полями переданного объекта. Для сравнения строк можно использовать метод equals()

Пример переопределения метода equals() :

public class MyClass  private int value; public boolean equals(Object obj)  if (this == obj)  return true; > if (obj == null || getClass() != obj.getClass())  return false; > MyClass myClass = (MyClass) obj; return value == myClass.value; > > 

В данном примере метод equals() сравнивает два объекта класса MyClass по полю value . Если значения полей равны, метод возвращает true , иначе — false

Как сравнить строки в Java? Сравниваем строки в Java

В этой статье мы рассмотрим операторы и методы сравнения строк в Java. Поговорим про особенности использования оператора == , а также про методы equals(), equalsIgnoreCase и compareTo(), т. к. они используются чаще всего.

Оператор для сравнения строк «==»

В первую очередь, надо сказать, что этот оператор проверяет и сравнивает не значения, а ссылки. С его помощью вы сможете проверить, являются ли сравниваемые вами элементы одним и тем же объектом. Когда 2 переменные String указывают на тот же самый объект в памяти, сравнение вернёт true, в обратном случае — false.

 
"Java" == "Java" //true

В примере выше литералы интернируются компилятором, в результате чего ссылаются на один и тот же объект.

 
new String("Java") == "Java" // false

Вышеприведённые переменные String указывают уже на различные объекты.

 
new String("Java") == new String("Java") // false

Здесь тоже вышеприведенные переменные String указывают на различные объекты.

Итак, мы видим, что оператор == по сути, сравнивает не две строки, а лишь ссылки, на которые указывают строки.

 
class TestClass< public static void main (String[] args)< // ссылается на тот же объект, возвращая true if( "Java" == "Java" )< System.out.println("Statement is true"); >else < System.out.println("Statement is false"); >// указывает уже на другой объект, возвращая false if(new String("Java") == "Java")< System.out.println("Statement is true"); >else < System.out.println("Statement is false"); >// указывает тоже на другой объект, возвращая false if(new String("Java") == new String("Java") )< System.out.println("Statement is true"); >else < System.out.println("Statement is false"); >> >

Итог:

 
Statement is true Statement is false Statement is false

Метод сравнения String equals()

Сравнение строк с помощью equals позволяет проверять исходное содержимое строки. Метод возвращает true, когда параметр — объект String, представляющий собой ту же строку символов, что и объект:

 
Objects.equals("Java", new String("Java")) //true

Когда надо выполнить проверку, имеют ли 2 строки одинаковое значение, мы можем задействовать Objects.equals() .

 
class TestClass< public static void main (String[] args) < String str1 = "Java"; String str2 = "Java"; String str3 = "ASP"; String str4 = "JAVA"; String str5 = new String("Java"); // оба равны и возвращают true if(str1.equals(str2))< System.out.println("Statement is true"); >else < System.out.println("Statement is false"); >// оба не равны и возвращают false if(str1.equals(str3))< System.out.println("Statement is true"); >else < System.out.println("Statement is false"); >// оба не равны и возвращают false if(str1.equals(str4))< System.out.println("Statement is true"); >else < System.out.println("Statement is false"); >// оба равны и возвращают true if(str1.equals(str5))< System.out.println("Statement is true"); >else < System.out.println("Statement is false"); >> >

Итог:

 
Statement is true Statement is false Statement is false Statement is true

Метод сравнения String equalsIgnoreCase()

С помощью метода equalsIgnoreCase() вы выполните сравнение строк, что называется, лексикографически, причём различия регистра будут игнорированы. Здесь значение true возвращается в том случае, если аргумент является объектом String и представляет такую же последовательность символов, что и у объекта. Прекрасное решение, если надо осуществить проверку строки на равенство, не учитывая при этом регистр.

 
class TestClass< public static void main (String[] args)< String str1 = "Java"; String str2 = "JAVA"; // возвращается true, ведь обе строки равны без учёта регистра if(str1.equalsIgnoreCase(str2))< System.out.println("Statement is true"); >else < System.out.println("Statement is false"); >// возвращается false, т. к. учитывается регистр символов if(str1.equals(str2))< System.out.println("Statement is true"); >else < System.out.println("Statement is false"); >> >
 
Statement is true Statement is false

Метод сравнения String compareTo()

Метод сравнения compareTo() применяется, если надо определить лексикографический порядок строк. Он выполняет сравнение значения char, действуя аналогично equals(). Когда 2 строки совпадают, compareTo() вернёт значение «ноль» (результат = 0). Сравнивая 2 строки, он вернёт положительное целое число (результат > 0), если 1-й объект String следует за 2-й строкой. Соответственно, метод вернёт отрицательный результат (результат < 0), когда 1-й объект String будет предшествовать 2-й строке:

 
result1 == result2 :возвращается 0; result1 > result2 :возвращается положительное значение; result1 < result2 : возвращается отрицательное значение.

Приведём пример:

 
class TestClass < public static void main (String[] args) < String str1 = "Java"; String str2 = "Java"; String str3 = "ASP"; int val = 0; val = str1.compareTo(str2); System.out.println(val); val = str1.compareTo(str3); System.out.println(val); val = str3.compareTo(str1); System.out.println(val); >>

Итог:

 
0 9 -9

На этом всё, очень надеемся, что этот материал будет вам полезен при сравнении строк в "Джава".

При подготовке статьи использовалась публикация «String Comparison in Java».

Хотите знать больше? Приходите на курс!

15.8. Java – Метод equals()

Метод equals() – сравнивает строку с указанным объектом. Результатом является значение true только в том случае, если аргумент не равен null и является строковым объектом (String), который представляет ту же последовательность символов как и этот объект.

Синтаксис

public boolean equals(Object anObject) 

Параметры

Подробная информация о параметрах:

  • anObject – объект, с которым сравниваем данную строку.

Возвращаемое значение

  • В Java equals() возвращает значение true, если строки равны; в противном случае значение false.

Пример

public class Test < public static void main(String args[]) < String Str1 = "Добро пожаловать на ProgLang.su"; String Str2 = Str1; String Str3 = new String("Сайт для изучения программирования"); boolean retVal; retVal = Str1.equals(Str2); System.out.println("Строка Str1 равна строке Str2? Ответ: " + retVal ); retVal = Str1.equals(Str3); System.out.println("Строка Str1 равна строке Str3? Ответ: " + retVal ); >> 

Получим следующий результат:

Строка Str1 равна строке Str2? Ответ: true Строка Str1 равна строке Str3? Ответ: false 

Оглавление

  • 1. Java – Самоучитель для начинающих
  • 2. Java – Обзор языка
  • 3. Java – Установка и настройка
  • 4. Java – Синтаксис
  • 5. Java – Классы и объекты
  • 6. Java – Конструкторы
  • 7. Java – Типы данных и литералы
  • 8. Java – Типы переменных
  • 9. Java – Модификаторы
  • 10. Java – Операторы
  • 11. Java – Циклы и операторы цикла
  • 11.1. Java – Цикл while
  • 11.2. Java – Цикл for
  • 11.3. Java – Улучшенный цикл for
  • 11.4. Java – Цикл do..while
  • 11.5. Java – Оператор break
  • 11.6. Java – Оператор continue
  • 12. Java – Операторы принятия решений
  • 12.1. Java – Оператор if
  • 12.2. Java – Оператор if..else
  • 12.3. Java – Вложенный оператор if
  • 12.4. Java – Оператор switch..case
  • 12.5. Java – Условный оператор (? 🙂
  • 13. Java – Числа
  • 13.1. Java – Методы byteValue(), shortValue(), intValue(), longValue(), floatValue(), doubleValue()
  • 13.2. Java – Метод compareTo()
  • 13.3. Java – Метод equals()
  • 13.4. Java – Метод valueOf()
  • 13.5. Java – Метод toString()
  • 13.6. Java – Метод parseInt()
  • 13.7. Java – Метод Math.abs()
  • 13.8. Java – Метод Math.ceil()
  • 13.9. Java – Метод Math.floor()
  • 13.10. Java – Метод Math.rint()
  • 13.11. Java – Метод Math.round()
  • 13.12. Java – Метод Math.min()
  • 13.13. Java – Метод Math.max()
  • 13.14. Java – Метод Math.exp()
  • 13.15. Java – Метод Math.log()
  • 13.16. Java – Метод Math.pow()
  • 13.17. Java – Метод Math.sqrt()
  • 13.18. Java – Метод Math.sin()
  • 13.19. Java – Метод Math.cos()
  • 13.20. Java – Метод Math.tan()
  • 13.21. Java – Метод Math.asin()
  • 13.22. Java – Метод Math.acos()
  • 13.23. Java – Метод Math.atan()
  • 13.24. Java – Метод Math.atan2()
  • 13.25. Java – Метод Math.toDegrees()
  • 13.26. Java – Метод Math.toRadians()
  • 13.27. Java – Метод Math.random()
  • 14. Java – Символы
  • 14.1. Java – Метод Character.isLetter()
  • 14.2. Java – Метод Character.isDigit()
  • 14.3. Java – Метод Character.isWhitespace()
  • 14.4. Java – Метод Character.isUpperCase()
  • 14.5. Java – Метод Character.isLowerCase()
  • 14.6. Java – Метод Character.toUpperCase()
  • 14.7. Java – Метод Character.toLowerCase()
  • 14.8. Java – Метод Character.toString()
  • 15. Java – Строки
  • 15.1. Java – Метод charAt()
  • 15.2. Java – Метод compareTo()
  • 15.3. Java – Метод compareToIgnoreCase()
  • 15.4. Java – Метод concat()
  • 15.5. Java – Метод contentEquals()
  • 15.6. Java – Метод copyValueOf()
  • 15.7. Java – Метод endsWith()
  • 15.8. Java – Метод equals()
  • 15.9. Java – Метод equalsIgnoreCase()
  • 15.10. Java – Метод getBytes()
  • 15.11. Java – Метод getChars()
  • 15.12. Java – Метод hashCode()
  • 15.13. Java – Метод indexOf()
  • 15.14. Java – Метод intern()
  • 15.15. Java – Метод lastIndexOf()
  • 15.16. Java – Метод length()
  • 15.17. Java – Метод matches()
  • 15.18. Java – Метод regionMatches()
  • 15.19. Java – Метод replace()
  • 15.20. Java – Метод replaceAll()
  • 15.21. Java – Метод replaceFirst()
  • 15.22. Java – Метод split()
  • 15.23. Java – Метод startsWith()
  • 15.24. Java – Метод subSequence()
  • 15.25. Java – Метод substring()
  • 15.26. Java – Метод toCharArray()
  • 15.27. Java – Метод toLowerCase()
  • 15.28. Java – Метод toString()
  • 15.29. Java – Метод toUpperCase()
  • 15.30. Java – Метод trim()
  • 15.31. Java – Метод valueOf()
  • 15.32. Java – Классы StringBuilder и StringBuffer
  • 15.32.1. Java – Метод append()
  • 15.32.2. Java – Метод reverse()
  • 15.32.3. Java – Метод delete()
  • 15.32.4. Java – Метод insert()
  • 15.32.5. Java – Метод replace()
  • 16. Java – Массивы
  • 17. Java – Дата и время
  • 18. Java – Регулярные выражения
  • 19. Java – Методы
  • 20. Java – Потоки ввода/вывода, файлы и каталоги
  • 20.1. Java – Класс ByteArrayInputStream
  • 20.2. Java – Класс DataInputStream
  • 20.3. Java – Класс ByteArrayOutputStream
  • 20.4. Java – Класс DataOutputStream
  • 20.5. Java – Класс File
  • 20.6. Java – Класс FileReader
  • 20.7. Java – Класс FileWriter
  • 21. Java – Исключения
  • 21.1. Java – Встроенные исключения
  • 22. Java – Вложенные и внутренние классы
  • 23. Java – Наследование
  • 24. Java – Переопределение
  • 25. Java – Полиморфизм
  • 26. Java – Абстракция
  • 27. Java – Инкапсуляция
  • 28. Java – Интерфейсы
  • 29. Java – Пакеты
  • 30. Java – Структуры данных
  • 30.1. Java – Интерфейс Enumeration
  • 30.2. Java – Класс BitSet
  • 30.3. Java – Класс Vector
  • 30.4. Java – Класс Stack
  • 30.5. Java – Класс Dictionary
  • 30.6. Java – Класс Hashtable
  • 30.7. Java – Класс Properties
  • 31. Java – Коллекции
  • 31.1. Java – Интерфейс Collection
  • 31.2. Java – Интерфейс List
  • 31.3. Java – Интерфейс Set
  • 31.4. Java – Интерфейс SortedSet
  • 31.5. Java – Интерфейс Map
  • 31.6. Java – Интерфейс Map.Entry
  • 31.7. Java – Интерфейс SortedMap
  • 31.8. Java – Класс LinkedList
  • 31.9. Java – Класс ArrayList
  • 31.10. Java – Класс HashSet
  • 31.11. Java – Класс LinkedHashSet
  • 31.12. Java – Класс TreeSet
  • 31.13. Java – Класс HashMap
  • 31.14. Java – Класс TreeMap
  • 31.15. Java – Класс WeakHashMap
  • 31.16. Java – Класс LinkedHashMap
  • 31.17. Java – Класс IdentityHashMap
  • 31.18. Java – Алгоритмы Collection
  • 31.19. Java – Iterator и ListIterator
  • 31.20. Java – Comparator
  • 32. Java – Дженерики
  • 33. Java – Сериализация
  • 34. Java – Сеть
  • 34.1. Java – Обработка URL
  • 35. Java – Отправка Email
  • 36. Java – Многопоточность
  • 36.1. Java – Синхронизация потоков
  • 36.2. Java – Межпоточная связь
  • 36.3. Java – Взаимная блокировка потоков
  • 36.4. Java – Управление потоками
  • 37. Java – Основы работы с апплетами
  • 38. Java – Javadoc

Методы equals() и hashcode() в языке Java

Разберём equals и hashCode в Java: поговорим о различии методов, контрактов, а также посмотрим на реальные примеры использования.

Методы equals и hashCode в Java в чём-то очень схожи, и даже вместе генерируются средствами IDE, таких как IntelliJ IDEA. Что в них общего, каковы отличия, и что будет, если использовать только один из методов?

  1. Метод equals()
  2. Контракт equals()
  3. Использование equals
  4. Метод hashcode()
  5. Контракт hashCode()
  6. Использование hashCode
  7. Почему equals и hashCode в Java переопределяются вместе

Метод equals() в Java

Как вы наверняка знаете, сравнение посредством == в Java сравнивает ссылки, но объекты таким образом не сравнить. Следующий пример подобного сравнения двух строк вернёт false :

public static void main(String[] args) < //false System.out.println(new String("Tproger") == new String("Tproger")); > 

Пусть значения и одинаковы, но переменные String указывают на разные объекты.

Тут-то в игру и вступает метод equals() , предусмотренный в Java для сравнения именно объектов. Данный метод проверяет два объекта одного происхождения на логическую равность.

То есть, сравнивая два объекта, программисту необходимо понять, эквивалентны ли их поля. При этом необязательно все поля должны быть идентичными, поскольку метод equals() подразумевает именно логическое равенство.

Контракт equals() в Java

Используя equals , мы должны придерживаться основных правил, определённых в спецификации Java:

  1. Рефлексивность — x.equals(x) возвращает true .
  2. Симметричность — x.equals(y) y.equals(x) .
  3. Транзитивность — x.equals(y) y.equals(z) x.equals(z) .
  4. Согласованность — повторный вызов x.equals(y) должен возвращать значение предыдущего вызова, если сравниваемые поля не изменялись.
  5. Сравнение null — x.equals(null) возвращает false .

Использование equals

Предположим, у нас есть класс Programmer , в котором предусмотрены поля с должностью и зарплатой:

public class Programmer < private final String position; private final int salary; protected Programmer(String position, int salary) < this.position = position; this.salary = salary; >> 

В переопределённом методе equals() обе переменные участвуют в проверке. Также вы всегда можете убрать ту переменную, которую не хотите проверять на равенство.

Зачастую метод equals в Java определяется вместе с hashCode, но здесь мы рассмотрим первый метод отдельно:

@Override public boolean equals(Object o)

Определим объекты programmer1 и programmer2 типа Programmer с одинаковыми значениями. При их сравнении с помощью == вернётся false , так как это разные объекты. Если же мы используем для сравнения метод equals() , вернётся true :

public class Main extends Programmer < protected Main(String position, int salary) < super(position, salary); >public static void main(String[] args) < Programmer programmer1 = new Programmer("Junior", 300); Programmer programmer2 = new Programmer("Junior", 300); //false System.out.println(programmer1 == programmer2); //true System.out.println(programmer1.equals(programmer2)); >> 

А вот такой результат мы получим, если хотя бы одна переменная (обозначенное поле объекта) из метода equals() не совпадёт:

public class Main extends Programmer < protected Main(String position, int salary) < super(position, salary); >public static void main(String[] args) < Programmer programmer1 = new Programmer("Junior", 300); Programmer programmer2 = new Programmer("Middle", 300); //false System.out.println(programmer1 == programmer2); //false System.out.println(programmer1.equals(programmer2)); >> 

Метод hashcode() в Java

Наконец, мы дошли до сравнения методов equals и hashCode в языке Java.

Фундаментальное отличие в том, что hashCode() — это метод для получения уникального целочисленного номера объекта, своего рода его идентификатор. Благодаря хешу (номеру) можно, например, быстро определить местонахождение объекта в коллекции.

Это число используется в основном в хеш-таблицах, таких как HashMap . При этом хеш-функция получения числа на основе объекта должна быть реализована таким образом, чтобы обеспечить равномерное распределение элементов по хэш-таблице. А также минимизировать возможность появления коллизий, когда по разным ключам функция вернёт одинаковое значение.

В случае Java, метод hashCode() возвращает для любого объекта 32-битное число типа int . Сравнить два числа между собой гораздо быстрее, чем сравнить два объекта методом equals() , особенно если в нём используется много полей.

Контракт hashCode() в Java

  1. Повторный вызов hashCode для одного и того же объекта должен возвращать одинаковые хеш-значения, если поля объекта, участвующие в вычислении значения, не менялись.
  2. Если equals() для двух объектов возвращает true , hashCode() также должен возвращать для них одно и то же число.
  3. При этом неравные между собой объекты могут иметь одинаковый hashCode .

Использование hashCode

Вернёмся к нашему классу Programmer . По-хорошему, вместе с equals() должен быть использован и метод hashCode():

public class Programmer < private final String position; private final int salary; protected Programmer(String position, int salary) < this.position = position; this.salary = salary; >@Override public boolean equals(Object o) < if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Programmer that = (Programmer) o; if (salary != that.salary) return false; return Objects.equals(position, that.position); >@Override public int hashCode() < int result = position != null ? position.hashCode() : 0; result = 31 * result + salary; return result; >> 

Почему equals и hashCode в Java переопределяются вместе

Сперва производится сравнение по хешу, чтобы понять, совпадают ли объекты, а только после подключается equals , чтобы определить, совпадают ли значения полей объекта.

Рассмотрим два сценария.

1. equals есть, hashCode нет

С точки зрения метода equals два объекта будут логически равны, но по hashCode они не будут иметь ничего общего. Таким образом, помещая некий объект в хэш-таблицу, мы рискуем не получить его обратно по ключу:

Map m = new HashMap<>(); m.put(new Point(1, 1), "Point A"); //pointName == null String pointName = m.get(new Point(1, 1)); 

2. hashCode есть, equals нет

Метод equals по умолчанию сравнивает указатели на объекты, определяя, ссылаются ли они на один и тот же объект. Следовательно, пример из предыдущего пункта по идее должен выполняться. Но мы по-прежнему не сможем найти наш объект в хэш-таблице.

Для успешного поиска объекта в хэш-таблице помимо сравнения хэш-значений ключа используется также определение логического равенства ключа с искомым объектом.

Следите за новыми постами по любимым темам

Подпишитесь на интересующие вас теги, чтобы следить за новыми постами и быть в курсе событий.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *