Impedir elementos repetidos - Lista Encadeada Circular - Java

Tendo o método de adicionar de forma circular elementos ao fim da lista, tenho que lançar uma exceção para caso tente adicionar elementos repetidos, já tentei com for, while, mas n consigo

public void add(String s) throws Exception {
//adicionar no final (funcionando)
TNo auxiliar = inicio;

	TNo novo = new TNo(s);
	if(inicio == null) {
		  inicio = novo;    
		} else {
		 
		  while (auxiliar.proximo != inicio) {
		    auxiliar = auxiliar.proximo;
		  }
		  auxiliar.proximo = novo;
		}
		novo.proximo = inicio;
}

Olá! permita-me tentar entender com uma pergunta.
Por qual motivo você não testa a lista com um filter.stream e retorna um boleano se encontrar uma repetição na lista?

Se observar o código, ele não está usando uma coleção da API do Java, ele está implementando sua própria lista circular.

Posta o fonte completo das tuas classes, incluindo a classe TNo.

não posso usar API

Não posso usar nenhuma API, tenho que percorrer a lista e comparar cada elemento com o parâmetro de entrada, caso seja igual jogar a exceção

Mas eu não disse que era pra usar.
Só expliquei pro @essevaiproale que você está implementando sua própria lista.

Posta suas classes, não temos como adivinhar a estrutura interna delas.

Essa é a classe e o método que deve retornar a exceção caso tente inserir um elemento repetido

public class ListaEncadeada implements TListaMiniProjeto {

private TNo inicio;
private TNo fim;

public ListaEncadeada() {
	inicio = null;
}

public void add(String s) throws Exception {
// adicionar no final (funcionando)

	TNo auxiliar = inicio;

	TNo novo = new TNo(s);
	if (inicio == null) {
		inicio = novo;
	} else {

		while (auxiliar.proximo != inicio) {
			auxiliar = auxiliar.proximo;
		}
		auxiliar.proximo = novo;
	}
	novo.proximo = inicio;
}

}

Essa é a classe com o método abstrato

public interface TListaMiniProjeto {

/**
 * esse método insere a entrada na lista. No caso de listas ordenadas, a inserção
 * acontece na posição adequada. No caso de listas desordenadas, a inserção acontece 
 * no final da lista.
 * @param s valor a ser guardado na lista
 * @throws Exception não deve ser possível inserir valores repetidos dentro da lista
 */
public void add(String s) throws Exception;

}

Essa é a classe e o método que deve retornar a exceção caso tente inserir um elemento repetido

public class ListaEncadeada implements TListaMiniProjeto {

private TNo inicio;
private TNo fim;

public ListaEncadeada() {
	inicio = null;
}

public void add(String s) throws Exception {
// adicionar no final (funcionando)

	TNo auxiliar = inicio;

	TNo novo = new TNo(s);
	if (inicio == null) {
		inicio = novo;
	} else {

		while (auxiliar.proximo != inicio) {
			auxiliar = auxiliar.proximo;
		}
		auxiliar.proximo = novo;
	}
	novo.proximo = inicio;
}

}

Essa é a classe com o método abstrato

public interface TListaMiniProjeto {

/**
 * esse método insere a entrada na lista. No caso de listas ordenadas, a inserção
 * acontece na posição adequada. No caso de listas desordenadas, a inserção acontece 
 * no final da lista.
 * @param s valor a ser guardado na lista
 * @throws Exception não deve ser possível inserir valores repetidos dentro da lista
 */
public void add(String s) throws Exception;

}

e a classe TNo

public class TNo {

public String dado;
public TNo proximo;


public TNo(String dado) {
	this.dado=dado;
}

}

fiz assim, vc acha que da certo?

public void add(String s) throws Exception {
// adicionar no final (funcionando)
TNo auxiliar = inicio;
while (auxiliar.dado != s) {
TNo novo = new TNo(s);
if (inicio == null) {
inicio = novo;
} else {

			while (auxiliar.proximo != inicio) {
				auxiliar = auxiliar.proximo;
			}
			auxiliar.proximo = novo;
		}
		novo.proximo = inicio;
	}
	throw new Exception ("Elemento já existe na lista");

}

Para os casos que estás a fazer, que é sempre inserir no final da lista, só tens de ir verificando, enquanto percorres a lista para chegar ao último elemento, se algum já tem o valor igual ao que queres adicionar.

    while (auxiliar.proximo != inicio) {
        if (auxiliar.dado.equals(s)) {
            throw new Exception ("Elemento já existe na lista");
        }
        auxiliar = auxiliar.proximo;
    }

Assim deve resolver:

public class ListaEncadeada implements TListaMiniProjeto {

    private TNo inicio;
    private TNo fim;

    public ListaEncadeada() {
        inicio = null;
    }

    public void add(String s) throws Exception {
        TNo novo = new TNo(s);
        if (inicio == null) {
            inicio = novo;
        } else {
            TNo auxiliar = inicio;
            verificaElemento(auxiliar, s);
            while (auxiliar.proximo != inicio) {
                auxiliar = auxiliar.proximo;
                verificaElemento(auxiliar, s);
            }
            auxiliar.proximo = novo;
        }
        novo.proximo = inicio;
    }

    private void verificaElemento(TNo no, String elemento) {
        String dado = no.dado;
        if (dado != null && dado.equals(elemento)) {
            throw new IllegalArgumentException("A lista já contém um elemento \"" + elemento + "\"");
        }
    }
}

Amigos, fiquei curioso por nunca passar por uma necessidade deste tipo. Em que caso haveria um impeditivo de usar algo simples e já existente? Seria para fins didaticos?

isso, professor quer que seja feito sem “ajuda” de apis

Vc fez algum curso superior da área? Normalmente os cursos, até os mais sem vergonhas, tem disciplinas de estruturas de dados. Essas coisas são vistas nessa disciplina ou em disciplinas correlatas. Eu dou aula disso há váááários anos… Se tiver interesse: https://www.youtube.com/playlist?list=PLqEuQ0dDknqUx2T9-gcu3eeDQeYt1Lqbt

Sim, Fiz BSI na FAE.Mas o que tem a ver com minha questão ao autor do tópico?

Em geral, é “melhor” usar o que já tem pronto (a menos que sua necessidade seja tão específica que precise de algo feito à parte).

Mas estudar estrutura de dados é importante para você entender o que são, onde vivem, o que comem para que servem e como usá-las (em quais casos é mais adequado usar e principalmente quando é melhor não usar). E geralmente nessas disciplinas você acaba implementando alguma(s) dela(s) para entender melhor como elas funcionam (como parece ser o caso, “o professor pediu”). Saber como as coisas funcionam ajuda a entendê-las melhor.

Então mesmo que na prática você vá usar algo pronto, é importante saber o que é esse algo, e se ele se encaixa no problema que você quer resolver.

Eu considero isso importantíssimo, mas que vejo muita gente negligenciando (e aí você vê gente usando array quando um map/hash/dicionário seria melhor ou vice-versa, enfim, usando uma estrutura quando outra seria melhor, etc). E escolher a estrutura de dados adequada é meio caminho para um código melhor.

Desculpe, você está certo. Respondi mal devido a misturar as coisas.
Fui grosseiro e infeliz.
Não vai acontecer novamente.

Que coisa, respondi na maior boa vontade, explicando meu ponto de vista e tal, porque achei que somente “sim” seria uma resposta meio inútil, e no fim você diz que eu atrapalhei…

Eu acho o contrário, respostas com uma ou duas frases mas que não explicam nada é que atrapalham, pois só geram ruído e não acrescentam nada à discussão.

Se fosse “mais do mesmo”, então seria algo tão óbvio que você nem precisaria ter perguntado. Mas como perguntou, achei que valia a pena responder.

Pelo visto me enganei…

1 curtida