Comparando String

15 respostas
Odyo

Galera, seguinte :

professor me passou um exercício e me pede pra ler um arquivo textual e quando encontrar determiandas palavras executar determinadas ações.

Eu criei uma classe Arquivo bem simples , para ler o arquivo texto mas não tá dando certo quando eu tendo identificar determinadas palavras

segue o código :

import java.io.*;

public class Arquivo
{
    private String [] comandos ={"#","inicio","escreve","fim"};
    private String linha="";
    private String fim="fim";
    
    private File arq;
    private BufferedReader arquivo_lido;
    
    // Cria novas instâncias da classe Arquivo
    public Arquivo(String caminho) throws IOException
    {
         arq = new File ( caminho );
         arquivo_lido= new BufferedReader(new FileReader(caminho));
    }
    
    // Método que lê o arquivo 
    public void ler_arquivo() throws IOException
    {
       while(linha!=fim) 
       {
            linha=arquivo_lido.readLine();
            System.out.println(linha);
       }
    }

    public void fecha_arquivo() throws IOException
    {
        arquivo_lido.close();
    }
    
}

no metodo ler_arquivo() eu coloco a condição de parada que se a String linha assumir “fim” o While para de ler o arquivo.

no tal arquivo existe uma lista simples de palavras :

aragorn
legolas
gimli
boromir
frodo
pipim
merry
sam
gandalf
fim

mas ao executar o tal metodo a palavra “fim” não é encontrada e o laço se torna infinito …

Alguém pode me dizer o que faço de errado ? como comparar a string linha com a palavra fim de modo que o laço funcione direitinho ?
:frowning:

15 Respostas

guilherme.chapiewski

Odyo,

Somente tipos primitivos (int, float, char, etc) são comparados com ==, !=, etc.

Strings são objetos e como todos os outros objetos são comparados através do método equals().

Sendo assim, o seu código ficaria:

while(!linha.equals("fim")) {
    ...
}
lenando

para evitar mais problemas ainda, use:

Assim nao importa se uma String esta com maiuscula e a outra nao.

Att.
Fernando

marcosbrandao

so complementando:

quando voce compara objetos, voce nao esta comparando o objeto em si e sim a referencia para este objeto. Por isso os objetos devem ser comparados com equals.
Por exemplo, voce pode ter dois objetos string com o conteudo igual. Se voce compara com ==, voce vai estar comparando a referencia que apontam pra objetos diferentes. Se vc usar equals, ele vai comparar o conteudo do objeto String que vai ser igual.

Compliquei ou ajudei?

flw

Odyo

Valeu !
já testei aqui e funcionou … !

eu já tinha tentado o usar o equals mas tava apanhando da linguagem …
tenho que estudar demais …

Mantu
guilherme.chapiewski:
Somente tipos primitivos (int, float, char, etc) são comparados com ==, !=, etc.
Não é bem assim... Você pode utilizar os operadores == e != para comparar variáveis de tipos não primitivos ([color=blue]variáveis do tipo referência para objeto[/color]). O que acontece é que estes operadores, quando operando sobre referências, verificam se os operandos referenciam um mesmo objeto na memória. Se tivermos, por exemplo, o seguinte código:
Integer int1 = new Integer(1);
Integer int2 = new Integer(1);
System.out.println(int1 == int2);
Teremos como saída no console:
false
Isso porque int1 está referenciando um determinado objeto Integer, que está em algum lugar da memória, e int2 está referenciando um outro objeto Integer, em outro lugar da memória. Logo, como int1 e int2 "apontam" para objetos distintos na memória, a operação "int1 == in2" retorna false e, consequentemente, a operação "int1 != int2" retorna true. Mas há um porém nessa história, principalmente quanto ao uso de strings. Se fizermos algo como:
String str1 = "blablabla";
String str2 = "blablabla";
System.out.println(str1 == str2);
O console nos mostrara o seguinte:
true
A priori, isto contradiz o que eu disse até agora. Mas o que acontece no caso dos objetos String é o seguinte: Por questão de performance, o Java mantém um tipo de "pool" de Strings dentro dos contextos. No exemplo acima, ao invés de o Java alocar na memória dois objetos String distintos na memória, ele, "vendo" que o conteúdo das strings são iguais, poupa memória e processamento alocando apenas um objeto String e fazendo com que este seja referenciado tanto por str1 quanto por str2. Você pode pensar que isso pode dar problema, porque uma variável pode alterar o conteúdo do objeto String e essa alteração se refletir para a(s) outra(s) variáveis. Porém, isso não acontece, pois objetos String são imutáveis. Mas note que esse lance do pool de String só (e sempre) funciona quando você cria variáveis String e lhes atribui um string literal, como feito no exemplo acima. Para "fugir" do pool de String (se você achar necessário por algum motivo), você deve intanciar o String explicitamente com o new:
String str1 = new String("blablabla");
String str2 = new String("blablabla");
System.out.println(str1 == str2);
Neste caso teremos a resposta:
false
Pois ordenamos, através do new, que fossem criados objetos String distintos.
guilherme.chapiewski:
Strings são objetos e como todos os outros objetos são comparados através do método equals()
Comparar objetos através do método equals só porque são objetos, não necessariamente garante-nos que estes objetos serão comparados de forma satisfatória ou semanticamente coerente... O que determina isso é se a classe dos objetos (Na verdade, a classe do objeto left-most) comparado sobrescreve ou não o método equals, definido na classe Object. Suponha a seguinte classe:
class UmaClasse{
	private int x;
	
	public UmaClasse(int x) {
		this.x = x;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}
}
Se executarmos o seguinte código:
UmaClasse
	umaClasse1 = new UmaClasse(10),
	umaClasse2 = new UmaClasse(10)
;
System.out.println(umaClasse1.equals(umaClasse2));
O resultado no console será
false
Como a classe UmaClasse não sobrescreve o método equals da classe Object, é exatamente este equals da classe Object que é executado. E você sabe o que é que está "escrito" dentro do equals da classe Object? Não? Olhe só:
package java.lang;

public class Object{
	//...
	public boolean equals(Object obj) {
		return (this == obj);
	}
	//...
}
A implementação dada pela classe Object ao método equals é exatamente a mesma coisa que se você fizesse uma comparação entre umaClasse1 e umaClasse2 utilizando o operador == !!! Logo, o equals não necessariamente terá um efeito diferente do ==... Isso vai depender se a classe do objeto que invoca o equals sobrescreve ou não este método. Eu costumo dizer que utilizamos o operador == para verificarmos se dois objetos são iguais, se dois objetos são, na verdade, um mesmo objeto. E utilizamos o método equals para verificar se dois objetos são equivalentes. Perceba que o critério que determina se dois objetos são equivalentes ou não é arbitrário. Depende única e exclusivamente da implementação que você dá ao método equals. Por exemplo, vamos estabelecer que o critério para que um dado objeto obj seja equivalente a um objeto do tipo UmaClasse deva atender aos seguintes requisitos: :arrow: obj deve ser não-nulo :arrow: obj deve ser um objeto do tipo UmaClasse ou compatível :arrow: obj - sendo ele um objeto do tipo UmaClasse - deve ter o valor do campo x igual ao valor do mesmo campo do objeto UmaClasse que está invocando o método equals. Para que os objetos da classe UmaClasse atendam a este critério de equivalência, esta classe deve sobrescrever o método equals da seguinte forma:
class UmaClasse{
	private int x;
	
	public UmaClasse(int x) {
		this.x = x;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}
	
	public boolean equals(Object obj) {
		if(obj == null)
			return false;
		
		if(!(obj instanceof UmaClasse))
			return false;
		
		UmaClasse other = (UmaClasse)obj;
		
		return this.x == other.x;
	}
}
Agora sim! Se executarmos novamente aquele código que comparava, através do equals, dois objetos do tipo UmaClasse, teremos no console o resultado
true
Mas, como eu disse antes, fomos nós quem determinamos o critério que determina se um objeto do tipo UmaClasse é equivalente ou não a um outro objeto do tipo Object... Nós poderiamos fazer qualquer tipo de estripulia na implementação do equals :twisted: Só de brincadeira: Vamos supor que, por algum motivo do além, os critérios que determinam se um objeto obj qualquer é equivalente a um objeto do tipo UmaClasse sejam os seguintes: :arrow: obj deve ser não-nulo :arrow: obj deve ser um objeto do tipo UmaClasse ou compatível :arrow: obj - sendo ele um objeto do tipo UmaClasse - deve ter seu campo x igual ao dobro do campo x do objeto UmaClasse que está invocando o método equals Essa doideria ficaria assim:
class UmaClasse{
	private int x;
	
	public UmaClasse(int x) {
		this.x = x;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}
	
	public boolean equals(Object obj) {
		if(obj == null)
			return false;
		
		if(!(obj instanceof UmaClasse))
			return false;
		
		UmaClasse other = (UmaClasse)obj;
		
		return 2*this.x == other.x;
	}
}
Neste caso, se executarmos estas linhas:
UmaClasse
	umaClasse1 = new UmaClasse(10),
	umaClasse2 = new UmaClasse(10),
	umaClasse3 = new UmaClasse(20)
;
System.out.println(umaClasse1.equals(umaClasse2));
System.out.println(umaClasse1.equals(umaClasse3));
Teremos a seguinte saída no console:
false
true
Mais um pouco de brincadeira? Ok: Seguem os seguintes critérios agora: :arrow: obj deve ser não-nulo :arrow: obj deve ser um objeto do tipo UmaClasse, Integer ou compatível com um destes. :arrow: Se obj é um objeto do tipo UmaClasse, seu campo x deve ter valor igual ao campo x do objeto que invocou o equals. :arrow: Se obj é um objeto do tipo Integer, deve ter valor igual ao valor do campo x do objeto UmaClasse que invocou o equals Essa coisa esdrúxula ficaria assim:
class UmaClasse{
	private int x;
	
	public UmaClasse(int x) {
		this.x = x;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}
	
	public boolean equals(Object obj) {
		if(obj == null)
			return false;
		
		if(obj instanceof UmaClasse) {
			UmaClasse other = (UmaClasse)obj;
			return this.x == other.x;
		}
		
		if(obj instanceof Integer) {
			Integer i = (Integer)obj;
			return this.x == i.intValue();
		}
		
		return false;
	}
}
Executem o seguinte código:
UmaClasse
	umaClasse1 = new UmaClasse(10),
	umaClasse2 = new UmaClasse(10)
;
System.out.println(umaClasse1.equals(umaClasse2));
System.out.println(umaClasse1.equals(new Integer(10)));
E terão a saída
true
true
Toda essa palhaçada foi só pra fixar o seguinte: É a implementação do método equals que determina o critério de equivalencia entre dois objetos. Tudo depende do que está escrito lá dentro, ou seja, depende apenas do que você põe lá dentro do equals. Recomento enfaticamente a leitura deste livro: http://www.amazon.com/Effective-Java-Programming-Language-Guide/dp/[telefone removido]/sr=8-1/qid=[telefone removido]/ref=pd_bbs_sr_1/102-7559920-2532931?ie=UTF8&s=books Este livro maravilhoso traz, entre outros tópicos importantissimos, uma análise do uso e implementação do método equals. Divirtam-se!
guilherme.chapiewski

Eu disse “Somente tipos primitivos (int, float, char, etc) são comparados com ==, !=, etc” e disse que ele DEVERIA usar equals() para objetos, mas não disse que os objetos não podem ser comparados com == :slight_smile:

Para um bom entendedor, meia palavra basta :smiley:

sapulha

Só lembrando que em Java 5 tem o tal do autoboxing , então se você utilizar:

Integer i1 = new Integer(100);
System.out.println( i1 == 100);

Vai dar true, coisa que não poderia ser feito nas versões anteriores.

Mantu

Ah tah! :smiley: Acho que você queria dizer “Tipos primitivos são comparados somente com ==, !=, etc”, ao invés de “Somente tipos primitivos são comparados com ==, !=, etc” (“Com ==, !=, etc, somente tipos primitivos são comparados”) :thumbup:, agora saquei… :mrgreen:

Meia palavra é uma coisa. Agora, má estruturação da frase, é outra… :smiley: :thumbup:

L

sapulha:
Só lembrando que em Java 5 tem o tal do autoboxing , então se você utilizar:

Integer i1 = new Integer(100);
System.out.println( i1 == 100);

Vai dar true, coisa que não poderia ser feito nas versões anteriores.

Mas é preciso tomar cuidado com essa abordagem, pq esse código que vc fez vai dar true, mas esse:

Integer i1 = new Integer(100);
Integer i2 = new Integer(100);
System.out.println( i1 == i2);

vai dar false, pois como nas versões anteriores do Java 5 da false, eles precisaram manter a compatibilidade. Não dá pra usar o autoboxing…

Eu sei que você sabia disso! É só pra deixar mais claro pra caso um novato venha ler esse post! :wink:

iwallas

Mantu:
guilherme.chapiewski:

Somente tipos primitivos (int, float, char, etc) são comparados com ==, !=, etc.

Não é bem assim… Você pode utilizar os operadores == e != para comparar variáveis de tipos não primitivos ([color=blue]variáveis do tipo referência para objeto[/color]). O que acontece é que estes operadores, quando operando sobre referências, verificam se os operandos referenciam um mesmo objeto na memória.
Se tivermos, por exemplo, o seguinte código:

Integer int1 = new Integer(1);
Integer int2 = new Integer(1);
System.out.println(int1 == int2);

Teremos como saída no console:

false

Opa… acho q é TRUE hein… Integer -127 até 127 comparados msm sendo objetos retorna true… =p

L

Eu testei e retorna FALSE!

iwallas

ops! falha nossa… vi agora q é só se for assim:

Integer x = 1;
Integer y = 1;

SOP(y==x);

ai sim retorna true…

Deh
public class Teste {

	public static void main(String... args){
		Integer i1 = 2;
		Integer i2 = 2;
		
		Integer i3 = new Integer(2);
		
		System.out.println(i1 == i3);
		System.out.println(i1 == i2);
	}
}

/**
 Saida:
    false
    true
*/

Quando você usa "new", o "==" só retorna true para a mesma intância...
e o autoboxing só vale para valores de "-128" à "127".

ViniGodoy

Esse papo do autoboxing só valer para valores de “-128” à “127” é arriscado.

Embora as VMs da Sun realmente tragam esse cache, ele não é garantido e não há promessas de que será mantido, reduzido ou ampliado nas próximas versões do Java.

O melhor mesmo é confiar na documentação e fazer a coisa do jeito certo.

I

Ressuscitando o topico, estou com um probleminha aqui pessoal.
tenho uma string com varias palavras, e quero verificar se uma determinada palavra existe dentro da String, existe algum metodo para isso? fiz o seguinte gato* talvez deixa mais claro o que quero:

String texto="um, dois, tres, quatro, cinco, seis, sete, oito, nove, dez!";
				
		for(int i=0;i<=texto.length()-4;++i){
			
			if(texto.substring(i, i+4).equals("sete")){
				System.out.println("Existe sete a String texto, está na posição "+i+","+(i+4));
			}
			
		}
Criado 13 de fevereiro de 2007
Ultima resposta 11 de jul. de 2008
Respostas 15
Participantes 11