Перейти к содержимому

Как сравнить два char в java

  • автор:

Developing.ru

Задача простая — найти в строке число, если нашли вернуть true. Решил что нужно перебрать каждый символ в строке и проверять его на значение от 0 до 9. Большой код писать не хочу, т.е можно было это if решить и проблем бы не было, но тут интересней решил подойти )) организовал вложенный цикл от 48 до 57 это код символов от 0 до 9, для проверки даже вывел их значение в конце метода, но чет if (stroka.charAt(1)==(char)k) никак не хочет сравнивать их. не пойму в чем загвоздка

Чем проще — тем оригинальней, а значит гениально, т.к. все гениальное — просто! Да! Кстати! Ctrl+V реально вставляет. ХDD

Сравнение объектов в Java

Сравнение объектов является важной функцией объектно-ориентированных языков программирования. В этом руководстве мы рассмотрим некоторые функции языка Java, которые позволяют нам сравнивать объекты. Также мы обратим внимание на подобные функции во внешних библиотеках.

Операторы == и !=

Давайте начем с операторов == и != , которые могут сказать, одинаковы ли Java-объекты или нет соответственно.

Примитивы

Для примитивных типов быть одинаковым означает иметь одинаковые значения:

assertThat(1 == 1).isTrue();

Благодаря автоматической распаковке это также работает при сравнении примитивного значения с его классом-оберткой:

Integer a = new Integer(1); assertThat(1 == a).isTrue();

Если две целочисленные переменные имеют разные значения, оператор == вернет false , а оператор != вернет true .

Объекты

Предположим, мы хотим сравнить два экземпляра классов-оберток Integer с одинаковыми значениями:

Integer a = new Integer(1); Integer b = new Integer(1); assertThat(a == b).isFalse();

При сравнении двух объектов их значения не равняются 1. Скорее различаются их адреса памяти в стеке, поскольку оба объекта создаются с использованием оператора new . Если мы присвоим переменной а переменную b , то получим другой результат:

Integer a = new Integer(1); Integer b = a; assertThat(a == b).isTrue();

Теперь давайте посмотрим, что происходит, когда мы используем фабричный метод Integer#valueOf :

Integer a = Integer.valueOf(1); Integer b = Integer.valueOf(1); assertThat(a == b).isTrue();

В этом случае они считаются одинаковыми. Это связано с тем, что метод valueOf() держит Integer в кеше, чтобы избежать создания слишком большого количества оберток с одинаковыми значениями. Поэтому метод возвращает один и тот же экземпляр Integer для обоих вызовов.

Java также делает это для переменных типа String:

assertThat("Hello!" == "Hello!").isTrue();

Однако, если они созданы с помощью оператора new , они не будут одинаковыми.

Наконец, две нулевые ссылки считаются одинаковыми, в то время как любой не-null объект считается отличным от null:

assertThat(null == null).isTrue(); assertThat("Hello!" == null).isFalse();

Конечно, поведение операторов равенства может быть ограничивающим. Что если мы хотим сравнить два объекта, расположенных по разным адресам и при этом полагать, что они равны на основании их внутренних состояний? Как это сделать, мы увидим в следующих пунктах.

Метод Object#equals

Теперь давайте поговорим о более широком концепте равенства с методом equals() .

Этот метод определен в классе Object , поэтому каждый объект Java наследует его. По умолчанию его реализация сравнивает адреса памяти объектов, поэтому он работает так же, как и оператор == . Однако мы можем переопределить этот метод, чтобы определить, что для наших объектов означает равенство внутренних состояний.

Во-первых, давайте посмотрим, как он ведет себя для существующих объектов, таких как Integer:

Integer a = new Integer(1); Integer b = new Integer(1); assertThat(a.equals(b)).isTrue();

Наш метод по-прежнему возвращает true, когда оба объекта одинаковы.

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

Мы также можем использовать метод equals() с любым пользовательским объектом. Допустим, у нас есть класс Person:

public class Person < private String firstName; private String lastName; public Person(String firstName, String lastName) < this.firstName = firstName; this.lastName = lastName; >>

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

@Override public boolean equals(Object o)

Чтобы узнать больше по этой теме, читайте вот эту статью.

Статический метод Objects#equals

Давайте посмотрим на статический метод Objects#equals . Ранее мы упоминали, что нельзя использовать null в качестве значения первого объекта, иначе будет выброшено исключение NullPointerException .

Метод equals() вспомогательного класса Objects решает эту проблему. Он принимает два аргумента и сравнивает их, а также обрабатывает значения null.

Давайте снова сравним объекты Person :

Person joe = new Person("Joe", "Portman"); Person joeAgain = new Person("Joe", "Portman"); Person natalie = new Person("Natalie", "Portman"); assertThat(Objects.equals(joe, joeAgain)).isTrue(); assertThat(Objects.equals(joe, natalie)).isFalse();

Как мы объяснили, этот метод обрабатывает значения null. Следовательно, если оба аргумента равны null, он вернет значение true, а если только один из них равен null, он вернет значение false.

Это может быть очень удобно. Допустим, мы хотим добавить не строго обязательную дату рождения в наш класс Person :

public Person(String firstName, String lastName, LocalDate birthDate)

Затем нужно обновить метод equals() , но с обработкой null значений. Мы можем сделать это, добавив условие в метод equals() :

birthDate == null ? that.birthDate == null : birthDate.equals(that.birthDate);

Однако же, если мы добавим слишком много полей с возможными null значениями в класс, он может стать запутанным. Использование метода Objects#equals в реализации equals() намного чище, что улучшает читаемость кода.

Objects.equals(birthDate, that.birthDate);

Интерфейс Comparable

Логику сравнения также можно использовать для размещения объектов в определенном порядке. Интерфейс Comparable позволяет нам определять порядок между объектами, выявляя, является ли объект больше, меньше или равным другому.

Интерфейс Comparable является дженериком и имеет только один метод, compareTo() , который принимает аргумент дженерик-типа и возвращает int. Возвращаемое значение отрицательное, если this меньше аргумента, 0, в случае если они равны, и положительное в обратном случае.

Допустим, в классе Person мы хотим сравнить объекты Person по их фамилии:

public class Person implements Comparable  < //. @Override public int compareTo(Person o) < return this.lastName.compareTo(o.lastName); >>

Метод compareTo() вернет отрицательный int, если оно вызвано с именем Person , имеющим большую фамилию, чем this, ноль, если ту же фамилию, и положительное значение в обратном случае.

Чтобы узнать подробнее, прочитайте статью на эту тему.

Интерфейс Comparator

Интерфейс Comparator является дженериком и содержит метод compare , который принимает два аргумента этого типа и возвращает integer. Мы ранее уже видели этот шаблон с интерфейсом Comparable.

Comparator аналогичен ему; однако он отделен от определения класс. Следовательно, мы можем определить столько Comparator , сколько захотим для одного класса, где мы можем предоставить только одну реализацию Comparable .

Представим, что у нас есть веб-страница, содержащая список людей в виде таблицы, и мы хотим предложить пользователю возможность сортировать их по именам, а не по фамилиям. Это невозможно с Comparable , если мы также хотим сохранить нашу текущую реализацию, но мы можем реализовать наши собственные Comparators .

Давайте создадим Person Comparator , который будет сравнивать их только по именам:

Comparator compareByFirstNames = Comparator.comparing(Person::getFirstName);

Теперь отсортируем список людей, используя Comparator :

Person joe = new Person("Joe", "Portman"); Person allan = new Person("Allan", "Dale"); List people = new ArrayList<>(); people.add(joe); people.add(allan); people.sort(compareByFirstNames); assertThat(people).containsExactly(allan, joe);

В интерфейсе Comparator есть и другие методы, которые мы можем использовать в реализации compareTo() :

@Override public int compareTo(Person o)

В этом примере мы сначала сравниваем фамилии, а затем имена. Затем мы сравниваем даты рождения, но, поскольку они нулевые, нужно рассказать, что с этим делать. Для этого мы задаем второй аргумент, чтобы сказать, что их нужно сравнить в соответствии с их естественным порядком, причем значения null идут последними.

Apache Commons

Давайте взглянем на библиотеку Apache Commons. Прежде всего, импортируем зависимость Maven.

 org.apache.commons commons-lang3 3.12.0 

Метод ObjectUtils#notEqual

Для начала поговорим о методе ObjectUtils#notEqual . Потребуется два аргумента Object , чтобы определить, не равны ли они, в соответствии с их собственной реализацией метода equals() . Он также обрабатывает значения null.

Используем наши примеры со String повторно:

String a = new String("Hello!"); String b = new String("Hello World!"); assertThat(ObjectUtils.notEqual(a, b)).isTrue();

Следует отметить, что у ObjectUtils есть метод equals() , что однако является устаревшим с момента возникновения Java 7, когда появились Objects#equals .

Метод ObjectUtils#compare

Теперь давайте сравним порядок объектов с помощью метода ObjectUtils#compare . Это дженерик-метод, который принимает два аргумента Comparable дженерик типа и возвращает Integer.

Приведем пример, снова используя Strings:

String first = new String("Hello!"); String second = new String("How are you?"); assertThat(ObjectUtils.compare(first, second)).isNegative();

По умолчанию этот метод обрабатывает значения null, считая их бОльшими. Он также предлагает перегруженную версию с аргументом boolean, которая предлагает изменить это поведение и считать их мЕньшими, принимая аргумент boolean.

Guava

Давайте взглянем на Guava. Прежде всего импортируем зависимость:

 com.google.guava guava 31.0.1-jre 

Метод Objects#equal

Как и библиотека Apache Commons, Google предоставляет нам метод определения равенства двух объектов, Objects#equal . Хотя у них разные реализации, возвращают они одинаковые результаты:

String a = new String("Hello!"); String b = new String("Hello!"); assertThat(Objects.equal(a, b)).isTrue();

Хотя он не помечен как устаревший, в JavaDoc говорится, что этот метод следует считать устаревшим, поскольку Java 7 предоставляет метод Objects#equals .

Методы сравнения

Библиотека Guava не предлагает метода для сравнения двух объектов (в следующем разделе мы увидим, что мы можем для этого сделать), но она предоставляет нам методы для сравнения примитивных значений. Давайте возьмем вспомогательный класс Ints и посмотрим, как работает его метод compare() :

assertThat(Ints.compare(1, 2)).isNegative();

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

Класс ComparisonChain

Наконец, библиотека Guava предлагает класс ComparisonChain , который позволяет нам сравнивать два объекта по цепочке сравнений. Мы можем легко сравнить два объекта Person по имени и фамилии:

Person natalie = new Person("Natalie", "Portman"); Person joe = new Person("Joe", "Portman"); int comparisonResult = ComparisonChain.start() .compare(natalie.getLastName(), joe.getLastName()) .compare(natalie.getFirstName(), joe.getFirstName()) .result(); assertThat(comparisonResult).isPositive();

Базовое сравнение достигается с помощью метода compareTo() , поэтому аргументы, передаваемые методам compare() , должны быть либо примитивными, либо Comparable.

Заключение

В этой статье мы узнали о разных способах сравнения объектов в Java. Мы изучили разницу между тождественностью, равенством и порядком. Мы также рассмотрели соответствующие функции в библиотеках Apache Commons и Guava.

Полный код из статьи можно найти на GitHub.

Приглашаем всех желающих на открытое занятие «Языки статической и динамической типизации». На этом вебинаре поговорим о стилях программирования и необходимости каждого из них. Разберём основные принципы объектно-ориентированного стиля (Инкапсуляция, Наследование, Полиморфизм). Рассмотрим возможности функционального стиля, которые предоставляет язык Java. Регистрация на вебинар.

  • Блог компании OTUS
  • Программирование
  • Java

Как сравнить два char в java

Хотя мы создали несколько переменных String со значениями Duke и Juggy , но в динамической памяти (куче) создаётся и хранится только два объекта. Для доказательства посмотрите следующий пример кода.

Напомним, что в Java оператор » == » используется для сравнения двух объектов и определения того, один и тот же это объект или нет.

String juggy = "Juggy"; String anotherJuggy = "Juggy"; System.out.println(juggy == anotherJuggy);

Этот код вернет true , потому что две переменные String указывают на один и тот же объект в пуле строк. Их значения одинаковые.

��☕ Интересные задачи по Java для практики можно найти на нашем телеграм-канале «Библиотека задач по Java»

Исключение – оператор new

Теперь посмотрите на этот код – он выглядит похожим на предыдущий пример, но здесь есть отличие.

String duke = new String("duke"); String anotherDuke = new String("duke"); System.out.println(duke == anotherDuke);

На основе предыдущего примера можно подумать, что этот код вернёт true , но это не так. Добавление оператора new приводит к созданию нового объекта String в памяти. Таким образом, JVM создаст два разных объекта.

Native-методы

Native-методы в Java – это методы, которые будут компилироваться с использованием языка C, обычно с целью управления памятью и оптимизации производительности.

Пулы строк и метод intern()

Для хранения строк в пуле используется способ, называемый «интернирование строк» (String interning).

Вот, что Javadoc говорит нам о методе intern() :

/** * Возвращает каноническое представление для строкового объекта. * * Пул строк (первоначально пустой) управляется классом . * * Когда вызывается метод intern, если пул уже содержит строку, * равную этому объекту , определяемому через * метод , тогда возвращается строка из пула. * Иначе, этот объект добавляется к * пулу и возвращается ссылка на этот объект . * * Из этого следует, что для любых двух строк и , * будет * тогда и только тогда, когда равно . * * Все литеральные строки и строковые константы интернируются. * Строковые литералы определяются в разделе 3.10.5 The Java™ Language Specification. * * @returns строка, которая имеет то же самое содержание как эта строка, * но, гарантируется, что она будет из пула уникальных строк. * * @jls 3.10.5 String Literals */ public native String intern();

Метод intern() используется для хранения строк в пуле строк. Во-первых, он проверяет, существует ли уже созданная строка в пуле. Если нет, то создает новую строку в пуле. Логика пула строк основана на паттерне Flyweight.

Теперь обратите внимание, что происходит, когда мы используем new для создания двух строк:

String duke = new String("duke"); String duke2 = new String("duke"); System.out.println(duke == duke2); // Здесь результат будет false System.out.println(duke.intern() == duke2.intern()); // Здесь результат будет true

В отличие от предыдущего примера с ключевым словом new , в данном случае сравнение вернёт true . Это потому, что использование метода intern() гарантирует, что строка будет в пуле.

Метод equals в классе String

Метод equals() используется для того, чтобы проверить одинаковое или нет состояние двух классов. Поскольку equals() находится к классе Object , то каждый Java-класс наследует его. Но метод equals() должен быть переопределен, чтобы он работал правильно. Конечно, String переопределяет 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; >

Как вы видите, значение класса String сравнивается через equals() , а не через ссылку на объект. Не имеет значения, если ссылки на объекты разные: будут сравниваться состояния.

Наиболее распространенные методы String

Есть ещё одна вещь, которую вам нужно знать, прежде чем решить задачку на сравнение строк.

Рассмотрим наиболее распространённые методы класса String :

// Удаляет пробелы в начале и в конце строки trim() // Получает подстроку по индексам substring(int beginIndex, int endIndex) // Возвращает длину строки length() // Заменяет строку, можно использовать регулярное выражение replaceAll(String regex, String replacement) // Проверяет, есть ли указанная последовательность CharSequence в строке contains(CharSequences)

Решите задачку на сравнение строк

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

В этой задаче вы сравните несколько строк, используя изученные концепции. Глядя на код ниже, можете ли вы определить значение каждой переменной result ?

public class ComparisonStringChallenge < public static void main(String. doYourBest) < String result = ""; result += " powerfulCode ".trim() == "powerfulCode" ? "0" : "1"; result += "flexibleCode" == "flexibleCode" ? "2" : "3"; result += new String("doYourBest") == new String("doYourBest") ? "4" : "5"; result += new String("noBugsProject") .equals("noBugsProject") ? "6" : "7"; result += new String("breakYourLimits").intern() == new String("breakYourLimits").intern() ? "8" : "9"; System.out.println(result); >>

Каков будет вывод?

  • A: 02468
  • B: 12469
  • C: 12579
  • D: 12568

Правильный ответ приведён в конце статьи.

Что сейчас произошло? Понимание поведения String

В первой строке мы видим:

result += " powerfulCode ".trim() == "powerfulCode" ? "0" : "1";

В этом случае результат false , ведь когда метод trim() удаляет пробелы, он создаёт новый String с помощью оператора new .

result += "flexibleCode" == "flexibleCode" ? "2" : "3";

Здесь нет никакой тайны, строки одинаковы в пуле строк. Это сравнение возвращает true .

result += new String("doYourBest") == new String("doYourBest") ? "4" : "5";

Использование new приводит к созданию двух новых строк, и не важно, равны их значения или нет. В этом случае сравнение будет false даже если значения одинаковые.

result += new String("noBugsProject") .equals("noBugsProject") ? "6" : "7";

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

В этом случае не имеет значения, разные объекты или нет, поскольку сравнивается значение. Результат true .

result += new String("breakYourLimits").intern() == new String("breakYourLimits").intern() ? "8" : "9";

Как вы видели ранее, метод intern() помещает строку в пул строк. Обе строки указывают на один и тот же объект, поэтому в данном случае true .

Распространенные ошибки со строками

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

Использование методов класса String для сравнения ссылок на объекты также может быть сложным. Особенность в том, что если метод изменяет что-то в строке, то будут разные ссылки на объекты.

Несколько примеров, которые помогут прояснить:

System.out.println("duke".trim() == "duke".trim());

Это сравнение будет истинным, потому что метод trim() не создает новую строку.

System.out.println(" duke".trim() == "duke".trim());

В этом случае первый метод trim() генерирует новую строку, так как метод будет выполнять свою работу, и поэтому ссылки разные.

Наконец, когда trim() выполнит свою работу, он создает новую строку:

// Реализация метода trim в классе String new String(Arrays.copyOfRange(val, index, index + len), LATIN1);

Что нужно помнить о строках

  • Строки неизменяемые, поэтому состояние строки изменить нельзя.
  • Для экономии памяти JVM хранит строки в пуле строк. При создании новой строки JVM проверяет ее значение и указывает на существующий объект. Если в пуле нет строки с этим значением, JVM создаёт новую строку.
  • Оператор » == » сравнивает ссылки на объект. Метод equals() сравнивает значения строк. То же правило будет применяться ко всем объектам.
  • При использовании оператора new будет создана новая строка в хипе (Прим. переводчика – в оригинале написано, что в пуле, но это не так, спасибо zagayevskiy), даже если есть строка с тем же значением.

Ответ

Ответ на эту задачу – D. Вывод будет 12568.

Как сравнить символы в строке java

Для сравнения символов в строке в Java можно использовать метод charAt() класса String . Этот метод возвращает символ по указанному индексу в строке.

String str = "Hello, World!"; char c = 'o'; for (int i = 0; i  str.length(); i++)  if (str.charAt(i) == c)  System.out.println("Symbol 'o' is present at index " + i); > > 

В данном примере мы проходим по всем символам в строке str и сравниваем их с символом c . Если символы совпадают, то выводим индекс символа в строке.

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

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