Ordernar String com mascara

Terei algo ± assim:

List<String> list = new ArrayList<String>(); list.add("Imposto INSS sem conta contábil."); list.add("Centro de custo 56 conta REF sem conta contábil."); list.add("Centro de Custo 18 plano financeiro 2.1.5.8 sem conta contábil."); list.add("Cliente 90 sem conta contábil."); list.add("Centro de Custo 89 plano financeiro 2.1.5.11 sem conta contábil."); list.add("Conta Corrente 3838302 sem conta contábil."); list.add("Centro de Custo 89 plano financeiro 2.1.5.9 sem conta contábil."); list.add("Parâmentro contábil Desconto sem conta contábil."); list.add("Centro de Custo 89 plano financeiro 2.1.5.28 sem conta contábil."); list.add("Parâmentro contábil Acréscimo sem conta contábil."); list.add("Centro de Custo 48 plano financeiro 2.1.5.8 sem conta contábil."); list.add("Centro de Custo 89 plano financeiro 2.1.5.10 sem conta contábil."); list.add("Centro de Custo 18 plano financeiro 2.1.5.9 sem conta contábil."); list.add("Cliente 23 sem conta contábil."); list.add("Imposto ISS sem conta contábil."); list.add("Centro de Custo 57 plano financeiro 2.1.5.18 sem conta contábil."); list.add("Conta Corrente 8986986 sem conta contábil."); list.add("Centro de Custo 89 plano financeiro 2.1.5.8 sem conta contábil."); list.add("Cliente 15 sem conta contábil."); list.add("Centro de Custo 89 plano financeiro 2.2.5.8 sem conta contábil."); list.add("Credor 16 sem conta contábil."); list.add("Centro de Custo 89 plano financeiro 2.1.5.12 sem conta contábil."); list.add("Credor 89 sem conta contábil."); list.add("Centro de Custo 57 plano financeiro 2.1.5.8 sem conta contábil."); list.add("Imposto CAUCAO sem conta contábil."); list.add("Centro de Custo 18 plano financeiro 2.1.5.18 sem conta contábil.");

Ordenando

Collections.sort(list);

A saída será assim:

Centro de Custo 18 plano financeiro 2.1.5.18 sem conta contábil. Centro de Custo 18 plano financeiro 2.1.5.8 sem conta contábil. Centro de Custo 18 plano financeiro 2.1.5.9 sem conta contábil. Centro de Custo 48 plano financeiro 2.1.5.8 sem conta contábil. Centro de Custo 57 plano financeiro 2.1.5.18 sem conta contábil. Centro de Custo 57 plano financeiro 2.1.5.8 sem conta contábil. Centro de Custo 89 plano financeiro 2.1.5.10 sem conta contábil. Centro de Custo 89 plano financeiro 2.1.5.11 sem conta contábil. Centro de Custo 89 plano financeiro 2.1.5.12 sem conta contábil. Centro de Custo 89 plano financeiro 2.1.5.28 sem conta contábil. Centro de Custo 89 plano financeiro 2.1.5.8 sem conta contábil. Centro de Custo 89 plano financeiro 2.1.5.9 sem conta contábil. Centro de Custo 89 plano financeiro 2.2.5.8 sem conta contábil. Centro de custo 56 conta REF sem conta contábil. Cliente 15 sem conta contábil. Cliente 23 sem conta contábil. Cliente 90 sem conta contábil. Conta Corrente 3838302 sem conta contábil. Conta Corrente 8986986 sem conta contábil. Credor 16 sem conta contábil. Credor 89 sem conta contábil. Imposto CAUCAO sem conta contábil. Imposto INSS sem conta contábil. Imposto ISS sem conta contábil. Parâmentro contábil Acréscimo sem conta contábil. Parâmentro contábil Desconto sem conta contábil.

Ficou quase perfeito, o “problema”

Centro de Custo 18 plano financeiro 2.1.5.18 sem conta contábil. Centro de Custo 18 plano financeiro 2.1.5.8 sem conta contábil. Centro de Custo 18 plano financeiro 2.1.5.9 sem conta contábil.

Gostaria que ficasse assim:

Centro de Custo 18 plano financeiro 2.1.5.8 sem conta contábil.
Centro de Custo 18 plano financeiro 2.1.5.9 sem conta contábil.
Centro de Custo 18 plano financeiro 2.1.5.18 sem conta contábil.

Acho q não tem como, ou tem?

Use a versão de Collections.sort que recebe um Comparator. A seguir, escreva um Comparator que leve isso em conta.

http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#sort(java.util.List,%20java.util.Comparator)

Opa,

Outra solução seria colocar o 0 na frente de números entre 1 e 9.

Opinião pessoal, não sei isso deve ser levado em consideração…
Ao meu entender, esse retorno gera duvida, pois parece que o retorno 2 é uma nova versão mais avançada que 1.

1. Centro de Custo 18 plano financeiro 2.1.5.18 sem conta contábil.
2. Centro de Custo 18 plano financeiro 2.1.5.8 sem conta contábil.
3. Centro de Custo 18 plano financeiro 2.1.5.9 sem conta contábil.

Aqui fica claro que o retorno 08 é inferior ao 09 e 18.

Centro de Custo 18 plano financeiro 2.1.5.08 sem conta contábil.
Centro de Custo 18 plano financeiro 2.1.5.09 sem conta contábil.
Centro de Custo 18 plano financeiro 2.1.5.18 sem conta contábil.

Da forma que esta, o usuário poderia entender como:

1. Centro de Custo 18 plano financeiro 2.1.5.18 sem conta contábil.
2. Centro de Custo 18 plano financeiro 2.1.5.80 sem conta contábil.
3. Centro de Custo 18 plano financeiro 2.1.5.90 sem conta contábil.

Mas ai vai da aplicação e do contexto…

[quote=entanglement]Use a versão de Collections.sort que recebe um Comparator. A seguir, escreva um Comparator que leve isso em conta.

http://docs.oracle.com/javase/6/docs/api/java/util/Collections.html#sort(java.util.List,%20java.util.Comparator)
[/quote]

eu até fiz um Comparator, o problema é fazer " leve isso em conta".

	public Comparator getComparator() {
		return new Comparator() {

			public int compare(Object o1, Object o2) {
				String arg0 = (String) o1;
				String arg1 = (String) o2;
				int retorno = arg0.compareToIgnoreCase(arg1);
				if (retorno != 0)
					return retorno;
				return retorno;
			};
		};
	}

Tens de fazer um split de cada string e ir verificando palavra a palavra, se é texto ou número. Se for texto, usas o compare da string, como estás a fazer. Se for número, convertes para número e comparas como número.

Feito meio em cima do joelho…

private static Comparator<String> getComparator() {  
        return new Comparator<String>() {  
      
            public int compare(String o1, String o2) {  
                String[] arg0 = o1.split("[ .]");  
                String[] arg1 = o2.split("[ .]");  

                //não pode comparar a totalidade das strings, apenas o numero de palavras em comum                
                int max = arg0.length;
                
                if (max>arg1.length){
                    max = arg1.length;
                }
        
               
                for (int i = 0;i<max;i++){
                    //se ambas as palavras são números, compara como número
                    if (isDigits(arg0[i]) && isDigits(arg1[i])){
                        int n1 = Integer.parseInt(arg0[i]);
                        int n2 = Integer.parseInt(arg1[i]);
                        if (n1 > n2){
                            return 1;
                        } else if (n2>n1){
                            return -1;
                        }
                    //senão compara como palavras
                    } else {
                        int retorno = arg0[i].compareToIgnoreCase(arg1[i]);
                        if (retorno != 0) {
                        	return retorno;
                        }
                    }
               }
               //nas partes comuns são semelhantes, deixo que seja comparado normalmente 
               // uma alternativa seria pelo numero de palavras da string. 
              // A que tivesse menos palavras seria a menor. Se tivessem igual número de palavras eram iguais
               return o1.compareToIgnoreCase(o2); 
               
                
            };  
        };  
    }  
    
    private static boolean isDigits (String s){
        return Pattern.matches("\\d+", s);
    }

vlw as respostas. pmlm fechou, testei seu metodo e aparentemente atende minha necessidade.