[RESOLVIDO] Criar método de comparação em algoritmo de ordenação para vetor de Strings

Olá, preciso fazer um trabalho de faculdade e estou tendo um problema com meu código. Eu tenho um botão que verifica se o vetor string tem algum indice vazio, se tiver, ele vai adicionar o valor que está no jtextfield neste indice e vai sair do laço de repetição, desta forma, eu vou poder adicionar o valor que eu quiser, quando eu quiser no vetor string. Logo depois, eu tenho um outro botão que pega o vetor com os valores que eu adicionei e ordena ele por um algoritmo de ordenação que ordena strings e mostra o valor já ordenado em um jtextarea (os valores do vetor são numeros, ent n tem erro na ordenação). O problema, é que se eu quiser adicionar apenas 2, ou 3, ou 4, ou 5 ou menos valores do que o indice do vetor permite, ou seja, deixar algum indice vazio, eu recebo um erro: Exception in thread “AWT-EventQueue-0” java.lang.NullPointerException. Alguem poderia me dizer como eu preencho o restante dos indices vazios (se tiver algum indice vazio) com valores que não afetem na ordenação?


//		Método para adicionar os valores do textField não editável ao vetor T:
		
		private void btnAddAoVetor_actionPerformed(ActionEvent e) {

			String a;
			int cont=0;
			
			if(textField.getText().equals("")){
				
				a=null;
				JOptionPane.showMessageDialog(null, "Selecione um dos dados da tabela!");
				
			}else {

				for(int i=0;i<=this.T.length;i++){
					
				a=String.valueOf(textField.getText());
				
				if(this.T[i]==null) {
					
					this.T[i]=String.valueOf(a.trim());
					JOptionPane.showMessageDialog(null, "Dados adicionados ao vetor!");
					
					break;
					}
				cont++;
			}
		}
			
			if(cont==this.T.length) {
			JOptionPane.showMessageDialog(null, "Impossível adicionar mais dados ao vetor!");
			}
			
		}
		
		
		
//		Botão para ordenar o vetor pelo método MergeSort e mostrar na tela:
	
		private void ordenarporMS_actionPerformed(ActionEvent e) {
			
//			algorítmo que verifica se à indices vazios no vetor T:
			 for(int i=0;i<=this.T.length;i++){
			    	
			        if(this.T[i]==null) {
			        	this.T[i]=String.valueOf("");   // ----> aqui o codigo coloca um valor vazio no indice que está nulo, ou vazio.
			        	break;
			        }else {if(this.T[i]!=null) {
			        	i++;
			        }
			        }
			     }
//			 fim do algoritimo de verificação.
			
			long inicio;
	        long fim;
	        
	        //tirando o tempo da ordenação:
	        
	        inicio = System.currentTimeMillis();
			
			MS.mergeSort(this.T);
			
			 fim = System.currentTimeMillis();
			 
			 System.out.printf("%.3f ms%n", (fim - inicio) / 1000d);  
			
			 for(String T1 : this.T) {
				textArea.append(T1.trim()+" - ");
			 }

		}

Aqui tenho o algoritmo de ordenação:


public class MS {
	
	public static void mergeSort(String[] T) {
		
        if (T.length > 1) {
        	
            String[] left = new String[T.length / 2];
            
            String[] right = new String[T.length - (T.length / 2)];

            for (int i = 0; i < left.length; i++) {
            	
                left[i] = T[i];
            }

            for (int i = 0; i < right.length; i++) {
            	
                right[i] = T[i + T.length / 2];
            }

            mergeSort(left);
            mergeSort(right);
            merge(T, left, right);
        }
    }

    public static void merge(String[] T, String[] left, String[] right) {
    	
        int a = 0;
        int b = 0;
        
        for (int i = 0; i < T.length; i++) {
        	
            if (b >= right.length || (a < left.length && left[a].compareToIgnoreCase(right[b]) < 0)) {
            	
                T[i] = left[a];
                a++;
                break;
            } else {
            	
                T[i] = right[b];
                b++;
                break;
            }
            
        }
    }
}

E aqui tem o erro:

Exception in thread “AWT-EventQueue-0” java.lang.NullPointerException
at algoritmoOrd.MS.merge(MS.java:36)
at algoritmoOrd.MS.mergeSort(MS.java:25)
at algoritmoOrd.MS.mergeSort(MS.java:23)
at algoritmoOrd.MS.mergeSort(MS.java:24)
at gui.Janela.ordenarporMS_actionPerformed(Janela.java:427)
at gui.Janela.access$1(Janela.java:405)
at gui.Janela$7.actionPerformed(Janela.java:195)
at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Window.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.awt.EventQueue$4.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)

Agradeço desde já a atenção. preciso muito disso, estou á meses procurando e já estou sem tempo :sweat:. Vlw!

A forma mais simples de resolver o problema seria usando listas, é possível converter a lista para vetor e não seria necessário alterar o sort:

String[] vetor = lista.toArray(new String[lista.size()]);

ou crie um método para comparar na classe MS e substitua o left[a].compareToIgnoreCase(right[b]) < 0:

private boolean aMenorQueB(String a, String b) {
  if (a == null) return false;
  if (b == null) return true;
  return a.compareToIgnoreCase(b) < 0;
}

e no merge:

if (b >= right.length || (a < left.length && aMenorQueB(left[a], right[b])) {
1 curtida

Opa! Vlw msm amigo! o algorítmo voltou a funcionar! Porém o resultado está saindo desorganizado: "18 - 18 - 22 - 27 - 26 - 24 - 26 - 23 - " e também está dando um erro toda vez que clico no botão de ordenar:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException
	at gui.Janela.ordenarporMS_actionPerformed(Janela.java:434)
	at gui.Janela.access$1(Janela.java:405)
	at gui.Janela$7.actionPerformed(Janela.java:195)
	at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
	at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
	at java.awt.Component.processMouseEvent(Unknown Source)
	at javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
	at java.awt.EventQueue.access$500(Unknown Source)
	at java.awt.EventQueue$3.run(Unknown Source)
	at java.awt.EventQueue$3.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.awt.EventQueue$4.run(Unknown Source)
	at java.awt.EventQueue$4.run(Unknown Source)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)

Você ou alguém tem alguma ideia de como resolver?

Obs: eu também tive que mudar o métod que vc me passou para “static”, só assim pra parar de dar erro, e eu tb n posso usar a lib pronta, tem que ser na mão msm.

O erro está na classe Janela na linha 434 no método ordenarporMS_actionPerformed

1 curtida

Sobre a ordenação, acho que se remover os breaks irá funcionar:

        T[i] = left[a];
        a++;
        // break;
    } else {
    	
        T[i] = right[b];
        b++;
        // break;

Outra observação, a String “2” é maior que “10” e o int 2 é menor que 10.

1 curtida

Esse seu left[a]compareToIgnoreCase vai lançar NullPointerException caso o elemento left[a] seja null.

Sugiro delegar essa comparação para um método compare que receba duas String como parâmetro e faça a tratativa caso alguma delas seja null.

Exemplo:

public class MS {

    public static void mergeSort(String[] T) {
        if (T.length > 1) {
            String[] left = new String[T.length / 2];
            String[] right = new String[T.length - (T.length / 2)];
            for (int i = 0; i < left.length; i++) {
                left[i] = T[i];
            }
            for (int i = 0; i < right.length; i++) {
                right[i] = T[i + T.length / 2];
            }
            mergeSort(left);
            mergeSort(right);
            merge(T, left, right);
        }
    }

    public static void merge(String[] T, String[] left, String[] right) {
        int a = 0;
        int b = 0;
        for (int i = 0; i < T.length; i++) {
            if (b >= right.length || (a < left.length && compare(left[a], right[b]) < 0)) {
                T[i] = left[a];
                a++;
                break;
            } else {
                T[i] = right[b];
                b++;
                break;
            }
        }
    }

    private static int compare(String left, String right) {
        // se as duas são a mesma referência ou são null não precisa reordenar, então retorna 0
        if (left == right) {
            return 0;
        }
        // se a da esquerda é null, retorna 1 positivo de forma que os valores nulos sempre fiquem à direita
        if (left == null) {
            return +1;
        }
        // se a da direita é null, retorna 1 negativo de forma que os valores nulos sempre fiquem à direita
        if (right == null) {
            return -1;
        }
        // se nenhuma das duas é null, efetua a comparação normalmente
        return left.compareToIgnoreCase(right);
    }
}
1 curtida

Caraca vlw msm! tirei os breaks tirei e apaguei aquela parte que verifica se à indices vazios no vetor, q n tava ajudando em nada, e agora está ordenando e sem erro! Ajudou muito! A, e mais uma coisa, vc ou alguém tem alguma dica de como eu posso imprimir o resultado da ordenação sem esses “nulls”? : "18 - 19 - 20 - 21 - null - null - null - null - null - null - ". Pelejei colocar o algoritmo que verificava se à indices vazios no vetor left e right mas não deu certo.

E também qual é a sintaxe desse codigo? :

Porque tenho q fazer a mesma coisa para 2 outros algoritmos de ordenação.
O Bubble Sort:

public class BS {
	
	private String[] vetor;
	public String[] getVetor() {
		return vetor;
	}
	public void setVetor(String[] vetor) {
		this.vetor = vetor;
	}
	public void bubbleSort() {
		int tamanho = vetor.length;
		for (int i = 0; i < tamanho - 1; i++) {
			for (int j = 0; j < tamanho - 1 - i; j++) {
				if(vetor[j].compareTo(vetor[ j+1 ])>0) { 
					String auxiliar = vetor[j];
					vetor[j] = vetor[j + 1];
					vetor[j + 1] = auxiliar;
				}
			}
		}
	}
}

E o Quick Sort:


public class QS {
	
	String txt[];
    int length;
	
	public void quickSort(String[]T) {
        if (T == null || T.length == 0) {
            return;
        }
        this.txt = T;
        this.length = T.length;
        sort(0, length - 1);
    }

   public void sort(int lowerIndex, int higherIndex) {
        int i = lowerIndex;
        int j = higherIndex;
        String pivot = this.txt[lowerIndex + (higherIndex - lowerIndex) / 2];

        while (i <= j) {
            while (this.txt[i].compareToIgnoreCase(pivot) < 0) {
                i++;
            }

            while (this.txt[j].compareToIgnoreCase(pivot) > 0) {
                j--;
            }

            if (i <= j) {
                trocarTextos(i, j);
                i++;
                j--;
            }
        }

        if (lowerIndex < j) {
            sort(lowerIndex, j);
        }
        if (i < higherIndex) {
            sort(i, higherIndex);
        }
    }
    
    public void trocarTextos(int i, int j) {
        String temp = this.txt[i];
        this.txt[i] = this.txt[j];
        this.txt[j] = temp;
    }

}

Porém, nos dois também dá erro no “compareToIgnoreCase”, Sabes como arrumar esse erro nos algoritmos de ordenação? Especialmente nesses dois?

Onde está:

    while (this.txt[i].compareToIgnoreCase(pivot) < 0) {
        i++;
    }

ficaria

    while (aMenorQueB(this.txt[i], pivot)) {
        i++;
    }

e

    while (this.txt[j].compareToIgnoreCase(pivot) > 0) {
        j--;
    }

para

    while (aMaiorQueB(this.txt[j], pivot)) {
        j--;
    }

vc teria que implementar as outras funções, ou usar um compare como o @staroski postou.

Para não imprimir valores nulos, tem duas opções:

criar um novo vetor sem valores nulos

int tamanho = 0;
// tem formas mais simples de fazer isso
while(vetor[tamanho] != null) {
  tamanho += 1;
}
String[] novoVetor = new String[tamanho];
for (int i = 0; i < novoVetor.length. i+=1) novoVetor[i] = vetor[i];
ordenarVetor(novoVetor);

ou montar String sem valores nulos

String resultado = "";
for(String valor: vetor) {
  if (valor == null) {
    resultado = resultado.substring(3);
    break;
  } else {
    resultado += " - " + valor;
  }
}
1 curtida

É só usar o mesma forma que sugeri no primeiro algoritmo, usa aquele método compare para comparar as Strings.

1 curtida

Vlw mesmo galera! Já estou à uns 2 meses cm esse trabalho aqui no pc e agora ta completo. Vocês me deram uma força enorme. Agora eu vi que falta muito pra mim ser um programador, não sou nem de perto um cara que olha para um algoritmo de ordenação desses e consegue ver que precisa fazer um método para comparar em vez de usar o da biblioteca java.