Pergunta

Suponha que dois objetos de string java:

String str = "<my string>";
String strLower = str.toLowerCase();

É então verdade que para cada valor de <my string> a expressão

str.length() == strLower.length()

avalia para true?

Então, faz String.toLowerCase() Preservar o comprimento da string original para qualquer valor da string?

Foi útil?

Solução

Surpreendentemente, sim não!!

De Java Docs of tolowercase

Converte todos os caracteres nesta string em minúsculas usando as regras do local especificado. O mapeamento de casos é baseado na versão padrão Unicode especificada pela classe de caracteres. Como os mapeamentos de casos nem sempre são 1: 1 mapeamentos de char, a sequência resultante pode ser um comprimento diferente da string original.

Exemplo:

package com.stackoverflow.q2357315;

import java.util.Locale;

public class Test {
    public static void main(String[] args) throws Exception {
        Locale.setDefault(new Locale("lt"));
        String s = "\u00cc";
        System.out.println(s + " (" + s.length() + ")"); // Ì (1)
        s = s.toLowerCase();
        System.out.println(s + " (" + s.length() + ")"); // i̇̀ (3)
    }
}

Outras dicas

Primeiro de tudo, gostaria de ressaltar que eu absolutamente concordo com a resposta (atualmente com a melhor classificação) do @Codaddict.

Mas eu queria fazer um experimento, então aqui está:

Não é uma prova formal, mas esse código foi executado para mim sem nunca chegar ao interior do if (Usando o JDK 1.6.0 Atualização 16 no Ubuntu):

Editar: Aqui está algum código atualizado que também lida com os locais:

import java.util.Locale;

public class ToLowerTester {
    public final Locale locale;

    public ToLowerTester(final Locale locale) {
        this.locale = locale;
    }

    public String findFirstStrangeTwoLetterCombination() {
        char[] b = new char[2];
        for (char c1 = 0; c1 < Character.MAX_VALUE; c1++) {
            b[0] = c1;
            for (char c2 = 0; c2 < Character.MAX_VALUE; c2++) {
                b[1] = c2;
                final String string = new String(b);
                String lower = string.toLowerCase(locale);
                if (string.length() != lower.length()) {
                    return string;
                }
            }
        }
        return null;
    }
    public static void main(final String[] args) {
        Locale[] locales;
        if (args.length != 0) {
            locales = new Locale[args.length];
            for (int i=0; i<args.length; i++) {
                locales[i] = new Locale(args[i]);
            }
        } else {
            locales = Locale.getAvailableLocales();
        }
        for (Locale locale : locales) {
            System.out.println("Testing " + locale + "...");
            String result = new ToLowerTester(locale).findFirstStrangeTwoLetterCombination();
            if (result != null) {
                String lower = result.toLowerCase(locale);
                System.out.println("Found strange two letter combination for locale "
                    + locale + ": <" + result + "> (" + result.length() + ") -> <"
                    + lower + "> (" + lower.length() + ")");
            }
        }
    }
}

Executar esse código com os nomes de localidade mencionados na resposta aceita imprimirá alguns exemplos. Executar sem argumento tentará todos os locais disponíveis (e demorará um bom tempo!).

Não é extenso, porque teoricamente pode haver cordas de vários caracteres que se comportam de maneira diferente, mas é uma boa primeira aproximação.

Observe também que muitas das combinações de dois caracteres produzidas dessa maneira são provavelmente inválidas UTF-16, então o fato de que nada explode nesse código só pode ser responsabilizado por uma API de string muito robusta em Java.

E por último, mas não menos importante: mesmo que a suposição seja verdadeira para a implementação atual do Java, isso pode mudar facilmente quando as versões futuras do Java implementam versões futuras do padrão Unicode, nas quais as regras para novos caracteres podem introduzir situações em que isso não permanece verdadeiro.

Então, dependendo disso, ainda é uma má ideia.

Lembre -se também de que o touppercase () também não preserva o comprimento. Exemplo: "Straße" se torna "Strasse" para o local alemão. Portanto, você está mais ou menos ferrado se estiver trabalhando com seqüências sensíveis ao caso e precisará armazenar o índice para algo.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top