JavaRush /Blogue Java /Random-PT /Igualdade em Java e comparação de strings - comparação de...

Igualdade em Java e comparação de strings - comparação de strings

Publicado no grupo Random-PT
Olá! Hoje falaremos sobre um tópico muito importante e interessante, a saber, comparar objetos entre si equals() em Java. E, de fato, em que casos em Java o Objeto A será igual ao Objeto B ? Igualdade e comparação de strings - 1Vamos tentar escrever um exemplo:
public class Car {

   String model;
   int maxSpeed;

   public static void main(String[] args) {

       Car car1 = new Car();
       car1.model = "Ferrari";
       car1.maxSpeed = 300;

       Car car2 = new Car();
       car2.model = "Ferrari";
       car2.maxSpeed = 300;

       System.out.println(car1 == car2);
   }
}
Saída do console:

false
Ok, pare. Por que, de fato, esses dois carros não são iguais? Demos a eles as mesmas propriedades, mas o resultado da comparação é falso. A resposta é simples. O operador ==compara não as propriedades dos objetos, mas os links. Mesmo que dois objetos tenham 500 propriedades idênticas, o resultado da comparação ainda será falso. Afinal, os links car1apontam car2 para dois objetos diferentes , para dois endereços diferentes. Imagine uma situação comparando pessoas. Provavelmente existe uma pessoa no mundo que tem o mesmo nome, cor dos olhos, idade, altura, cor do cabelo, etc. Ou seja, vocês são semelhantes em muitos aspectos, mas ainda assim não são gêmeos e, principalmente, não são a mesma pessoa. Igualdade e comparação de strings - 2O operador aplica aproximadamente a mesma lógica ==quando o usamos para comparar dois objetos. Mas e se você precisar de uma lógica diferente em seu programa? Por exemplo, se o seu programa simular análise de DNA. Ela deve comparar o código de DNA de duas pessoas e determinar que são gêmeas.
public class Man {

   int dnaCode;

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = 1111222233;

       Man man2 = new Man();
       man2.dnaCode = 1111222233;

       System.out.println(man1 == man2);
   }
}
Saída do console:

false
É lógico que o resultado foi o mesmo (afinal não mudamos nada), mas agora não estamos satisfeitos! Na verdade, na vida real, a análise de DNA é uma garantia de cem por cento de que estamos diante de gêmeos. Mas nosso programa e operador ==nos dizem o contrário. Como podemos mudar esse comportamento e garantir que, se os testes de DNA corresponderem, o programa produzirá o resultado correto? Para tanto, foi criado um método especial em Java - equals() .

Método Equals() em Java

Assim como o método toString()que discutimos anteriormente, equals() pertence à classe, Objecta classe mais importante em Java, da qual todas as outras classes são derivadas. No entanto, equals() em si não mudará o comportamento do nosso programa de forma alguma:
public class Man {

   String dnaCode;

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = "111122223333";

       Man man2 = new Man();
       man2.dnaCode = "111122223333";

       System.out.println(man1.equals(man2));
   }
}
Saída do console:

false
Exatamente o mesmo resultado, então por que esse método é necessário? :/ É simples. O fato é que agora utilizamos esse método conforme ele é implementado na própria classe Object. E se entrarmos no código da classe Objecte vermos como esse método é implementado nela e o que ele faz, veremos:
public boolean equals(Object obj) {
   return (this == obj);
}
Esta é a razão pela qual o comportamento do nosso programa não mudou! Dentro do método equals() da classe Objectencontra-se a mesma comparação de referência, ==. Mas o truque deste método é que podemos substituí-lo. Substituir significa escrever seu próprio método equals() em nossa classe Mane fazer com que ele se comporte da maneira que desejamos! Agora não estamos satisfeitos com o fato de a verificação man1.equals(man2)fazer essencialmente a mesma coisa que man1 == man2. Aqui está o que faremos nesta situação:
public class Man {

   int dnaCode;

   public boolean equals(Man man) {
       return this.dnaCode ==  man.dnaCode;
   }

   public static void main(String[] args) {

       Man man1 = new Man();
       man1.dnaCode = 1111222233;

       Man man2 = new Man();
       man2.dnaCode = 1111222233;

       System.out.println(man1.equals(man2));

   }
}
Saída do console:

true
Um resultado completamente diferente! Ao escrever nosso próprio método equals() em vez do método padrão, alcançamos o comportamento correto: agora, se duas pessoas têm o mesmo código de DNA, o programa nos diz: “A análise de DNA mostrou que são gêmeos” e retorna verdadeiro! Ao substituir o método equals() em suas classes, você pode criar facilmente a lógica de comparação de objetos necessária. Abordamos a comparação de objetos apenas em termos gerais. Ainda teremos uma grande palestra separada sobre este tópico (você pode lê-la rapidamente agora, se estiver interessado).

Comparação de strings em Java - comparação de strings

Por que tratamos as comparações de strings separadamente de todo o resto? Bem, na verdade, as linhas de programação são uma história totalmente diferente. Em primeiro lugar, se pegarmos todos os programas Java escritos pela humanidade, cerca de 25% dos objetos neles contidos são compostos por eles. Portanto, este tema é muito importante. Em segundo lugar, o processo de comparação de strings é bastante diferente de outros objetos. Vejamos um exemplo simples:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2);
   }
}
Saída do console:

false
Mas por que falso? As linhas são exatamente iguais, palavra por palavra :/ Você pode assumir: isso ocorre porque o operador == compara referências! Afinal, s1eles s2possuem endereços diferentes na memória. Se esse pensamento lhe ocorreu, então vamos refazer nosso exemplo:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = "JavaRush is the best site to learn Java!";
       System.out.println(s1 == s2);
   }
}
Agora também temos dois links, mas o resultado mudou para o oposto: Saída do console:

true
Completamente confuso? :) Vamos descobrir. Na verdade , o operador ==compara endereços na memória. Esta regra sempre funciona e não há necessidade de duvidar dela. Isso significa que se s1 == s2retornar verdadeiro, essas duas strings terão o mesmo endereço na memória. E de fato é! É hora de se familiarizar com uma área de memória especial para armazenar strings - o pool de strings ( String pool) Igualdade e comparação de strings - 3O pool de strings é uma área para armazenar todos os valores de string que você cria em seu programa. Para que foi criado? Conforme mencionado anteriormente, as strings ocupam uma grande parte de todos os objetos. Em qualquer programa grande, muitas linhas são criadas. Para economizar memória, é isso que é necessário String Pool- uma linha com o texto que você precisa é colocada ali e, no futuro, os links recém-criados referem-se à mesma área de memória, não há necessidade de alocar memória adicional a cada vez. Cada vez que você escreve String = “........”, o programa verifica se existe uma linha com esse texto no conjunto de strings. Se houver, não será criado um novo. E o novo link apontará para o mesmo endereço no conjunto de strings onde esta string está armazenada. Portanto, quando escrevemos no programa
String s1 = "JavaRush is the best site to learn Java!";
String s2 = "JavaRush is the best site to learn Java!";
o link s2aponta exatamente para o mesmo lugar que s1. O primeiro comando criou uma nova linha no conjunto de strings com o texto que precisávamos e, quando chegou ao segundo, simplesmente se referiu à mesma área de memória que s1. Você pode fazer pelo menos mais 500 linhas com o mesmo texto, o resultado não mudará. Parar. Mas por que esse exemplo não funcionou para nós antes?
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2);
   }
}
Acho que, intuitivamente, você já adivinha qual é o motivo :) Tente adivinhar antes de continuar lendo. Você pode ver que essas duas linhas foram criadas de forma diferente. Um é com a ajuda do operador newe o segundo é sem ele. Esta é precisamente a razão. O operador new, ao criar um objeto, aloca forçosamente uma nova área na memória para ele . E a linha criada com new, não termina em String Pool: ela se torna um objeto separado, mesmo que seu texto seja exatamente igual à mesma linha de String Pool'a. Isto é, se escrevermos o seguinte código:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = "JavaRush is the best site to learn Java!";
       String s3 = new String("JavaRush is the best site to learn Java!");
   }
}
Na memória ficará assim: Igualdade e comparação de strings - 4E toda vez que um novo objeto for criado, newuma nova área será alocada na memória, mesmo que o texto dentro das novas linhas seja o mesmo! Parece que resolvemos o operador ==, mas e o nosso novo amigo - o método equals()?
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1.equals(s2));
   }
}
Saída do console:

true
Interessante. Sabemos exatamente o que s1e s2apontamos para diferentes áreas da memória. Mesmo assim, o método equals() diz que eles são iguais. Por que? Lembre-se, acima dissemos que o método equals() pode ser substituído em sua classe para comparar objetos da maneira que você precisa? Foi o que fizeram com a aula String. Possui um método equals() substituído. E não compara links, mas sim a sequência de caracteres em strings. E se o texto nas strings for o mesmo, não importa como elas foram criadas e onde estão armazenadas: no pool de strings ou em uma área de memória separada. O resultado da comparação será verdadeiro. A propósito, Java permite comparar strings corretamente, sem diferenciar maiúsculas de minúsculas. Numa situação normal, se você escrever uma das linhas, por exemplo, em maiúsculas, o resultado da comparação será falso:
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JAVARUSH - ЛУЧШИЙ САЙТ ДЛЯ ИЗУЧЕНИЯ JAVA!");
       System.out.println(s1.equals(s2));
   }
}
Saída do console:

false
Para este caso, a classe Stringpossui um método equalsIgnoreCase(). Se o principal na sua comparação for a sequência de caracteres específicos, e não o caso deles, você poderá usá-lo. Por exemplo, isto será útil ao comparar dois endereços de e-mail:
public class Main {

   public static void main(String[] args) {

       String address1 = "Moscow, Academician Korolev street, 12";
       String address2 = new String("Г. МОСКВА, УЛ. АКАДЕМИКА КОРОЛЕВА, ДОМ 12");
       System.out.println(address1.equalsIgnoreCase(address2));
   }
}
Neste caso, é óbvio que se trata do mesmo endereço, pelo que utilizar o método equalsIgnoreCase()será a decisão acertada.

Método String.intern()

A classe Stringtem outro método complicado - intern(); O método intern()funciona diretamente com String Pool'om. Se você chamar um método intern()em uma string, ele:
  • Procura ver se há uma string com este texto no conjunto de strings
  • Se houver, retorna um link para ele no pool
  • Caso contrário, ele coloca uma linha com este texto no conjunto de strings e retorna um link para ele.
Ao aplicar o método intern()à referência de string que foi criada via new, podemos compará-lo com a referência de string de String Pool'a por meio do ==.
public class Main {

   public static void main(String[] args) {

       String s1 = "JavaRush is the best site to learn Java!";
       String s2 = new String("JavaRush is the best site to learn Java!");
       System.out.println(s1 == s2.intern());
   }
}
Saída do console:

true
Anteriormente, quando os comparávamos sem intern(), o resultado era falso. Agora o método intern()verificava se havia uma linha com o texto “JavaRush – o melhor site para aprender Java!” no conjunto de cordas. Claro que está lá: nós o criamos quando escrevemos
String s1 = "JavaRush is the best site to learn Java!";
Foi verificado que a referência s1e a referência retornada pelo método s2.intern()apontam para a mesma área da memória, e, claro, apontam :) Para resumir, lembre-se e use a regra principal: Para comparar strings, SEMPRE use o equals() método! Ao comparar strings, quase sempre você quer dizer comparar seu texto, não links, áreas de memória e assim por diante. O método equals() faz exatamente o que você precisa. Aqui estão alguns links para você estudar por conta própria:
Comentários
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION