Devo usar string.isEmpty () ou “” .equals (string)?

171

O título basicamente diz tudo. Normalmente, estou testando isso ao lado de a string == null, então não estou realmente preocupado com um teste com segurança nula. Qual devo usar?

String s = /* whatever */;
...
if (s == null || "".equals(s))
{
    // handle some edge case here
}

ou

if (s == null || s.isEmpty())
{
    // handle some edge case here
}

Na mesma nota - faz isEmpty()mesmo outra coisa senão return this.equals("");ou return this.length() == 0;?

Matt Ball
fonte
26
Lembre-se de que isEmpty()é apenas Java 6+.
ColinD 23/07
1
Você pode criar um método auxiliar Util.String.hasValue (String s) que verifica nulo, vazio e espaço em branco para lidar com todos os casos.
Cloudanger 23/07/10
5
@ColinD Provavelmente não é um problema - o J2SE 5.0 concluiu seu período de final de vida útil há algum tempo.
Tom Hawtin - defina
1
Outra coisa a considerar é "" .equals () usa Object como argumento, portanto você não receberá um erro de compilador se o tipo de argumento mudar de String para outra, para melhor ou para pior.
Paul Jackson

Respostas:

251

O principal benefício "".equals(s)é que você não precisa da verificação nula ( equalsirá verificar seu argumento e retornar falsese for nulo), com o qual você parece não se importar. Se você não está preocupado em sser nulo (ou está verificando isso), eu definitivamente usaria s.isEmpty(); mostra exatamente o que você está verificando, você se importa se sestá vazio ou não , se não é igual à string vazia

Michael Mrozek
fonte
29
Obrigado pela explicação. Agora eu sei por que favorecer "" .equals (str) sobre str.equals ("")! Eu sempre estava me perguntando por que outras pessoas usam isso com tanta frequência, mas não levam em consideração valores nulos. Ótimo :-)
Peter Wippermann
10
IMHO a verificação nula ainda é necessária nos exemplos acima, pois assumimos que a condição deve ser verdadeira para o valor nulo. s == nulo || "" .equals (s)
mkorpela 24/02
5
@ Master.Aurora não, se getValue()voltou nulo, você teria um NullPointerException quando toString()foi chamado
ataulm
12
@RenniePet Não é como se houvesse mágica envolvida. Se sfor nulo, você não pode chamar métodos nele - é nulo. ""nunca será nula, então você pode chamar métodos nele com segurança, e equals()pode lidar com o caso em que o seu argumento é nulo
Michael Mrozek
5
Uma observação sobre o desempenho: isEmpty()verifica o comprimento interno de uma matriz privada e equals(Object anObject)faz muito mais (por exemplo, verificação instanceof). Em termos de desempenho, isEmpty()geralmente é mais rápido.
precisa saber é o seguinte
82

String.equals("")é realmente um pouco mais lento do que apenas uma isEmpty()chamada. Strings armazenam uma variável de contagem inicializada no construtor, pois Strings são imutáveis.

isEmpty() compara a variável count a 0, enquanto igual verifica o tipo, o comprimento da string e, em seguida, itera sobre a string para comparação, se os tamanhos corresponderem.

Então, para responder sua pergunta, isEmpty()realmente fará muito menos! e isso é uma coisa boa.

David Young
fonte
3
Eu acho que neste caso a diferença não se aplica; nunca haverá uma iteração sobre as cordas para comparação, porque os tamanhos não correspondem (a menos que a corda na verdade está vazia, e então não há personagens para interagir sobre)
Michael Mrozek
2
Verdadeiro, mas com iguais, você realiza uma verificação de referência primeiro para ver se eles são o mesmo objeto, depois uma instância de, depois uma conversão para String, uma verificação de comprimento e, finalmente, a iteração. Se ambas as Strings estivessem vazias, seria apenas uma simples verificação de referência.
David Young
o código-fonte da classe String está disponível java2s.com/Open-Source/Java-Document/6.0-JDK-Core/lang/java/…
David Young
1
@David link morto; aqui vai viver um docjar.com/html/api/java/lang/String.java.html#1011
Matt Bola
17

Uma coisa que você pode considerar além das outras questões mencionadas é a isEmpty()introduzida na 1.6, portanto, se você a usar, não poderá executar o código no Java 1.5 ou abaixo.

Fabian Steeg
fonte
4
Definitivamente, isso não é uma preocupação para mim.
Matt Ball
1
Além disso, esta resposta é agora há 6 anos. Eu espero que ninguém precise mais usar nada antigo como o Java 1.5.
Misha Nasledov 27/09/16
1
De fato, existem muitas coisas que podem ser quebradas ao atualizar uma versão java. É menos crítico para um aplicativo back-end que roda em um servidor grande, mas é importante para aplicativos clientes. As bibliotecas gráficas e as estratégias de coleta de lixo são frequentemente afetadas por atualizações maiores e menores do java. Além disso, o software cliente pode ser executado em vários sistemas operacionais e, às vezes, com memória limitada, o que significa que muitas vezes você não tem orçamento / recursos para testar tudo. - Sim, tenho clientes que ainda ficar com Java 5 em 2017.
bvdb
15

Você pode usar o apache commons StringUtils isEmpty () ou isNotEmpty ().

CoolBeans
fonte
1
@ 2019 e ainda precisamos de uma biblioteca de terceiros para isso: suspiro:
Adam
2

Realmente não importa. "".equals(str)é mais claro na minha opinião.

isEmpty()retornos count == 0;

Kylar
fonte
47
Eu diria que str.isEmpty()é muito mais claro que "".equals(str). Lê como o que você está verificando. Questão de opinião, eu acho.
ColinD 23/07
7
Acho que algumas pessoas preferem "" .equals (str) para evitar o NPE. Eu pessoalmente não gosto disso, porque prefiro verificar se a string não é nula primeiro.
coolbeans
2

Eu escrevi uma classe de testador que pode testar o desempenho:

public class Tester
{
    public static void main(String[] args)
    {
        String text = "";

        int loopCount = 10000000;
        long startTime, endTime, duration1, duration2;

        startTime = System.nanoTime();
        for (int i = 0; i < loopCount; i++) {
            text.equals("");
        }
        endTime = System.nanoTime();
        duration1 = endTime - startTime;
        System.out.println(".equals(\"\") duration " +": \t" + duration1);

        startTime = System.nanoTime();
        for (int i = 0; i < loopCount; i++) {
            text.isEmpty();
        }
        endTime = System.nanoTime();
        duration2 = endTime - startTime;
        System.out.println(".isEmpty() duration "+": \t\t" + duration2);

        System.out.println("isEmpty() to equals(\"\") ratio: " + ((float)duration2 / (float)duration1));
    }
}

Descobri que o uso de .isEmpty () levava cerca de metade do tempo de .equals ("").

conapart3
fonte
Esta não é uma marca de microbench válida. Eu recomendo fortemente o uso do Caliper ou ferramenta de benchmarking semelhante criada para fins específicos. stackoverflow.com/q/504103/139010
Matt Bola
Obrigado pela dica! Quando tiver algum tempo livre, testarei alguns micro benchmarking e atualizarei minha resposta.
precisa saber é o seguinte