Remover caracteres à esquerda e à direita de uma sequência
1. Introdução
Neste breve tutorial, veremos várias maneiras de remover caracteres à esquerda e à direita de umString. Por uma questão de simplicidade, removeremos os zeros nos exemplos.
Com cada implementação, criaremos dois métodos: um para zeros à esquerda e outro para zeros à direita.
Esse problema tem um caso extremo: o que queremos fazer quando a entrada contém apenas zeros? Retornar umString vazio ou umString contendo um único zero? Veremos implementações para ambos os casos de uso em cada uma das soluções.
Temos testes de unidade para cada implementação, que você pode encontraron GitHub.
2. UsandoStringBuilder
Em nossa primeira solução, vamos criar umStringBuilder with the original String, and we’ll delete the unnecessary characters do início ou do fim:
String removeLeadingZeroes(String s) {
StringBuilder sb = new StringBuilder(s);
while (sb.length() > 0 && sb.charAt(0) == '0') {
sb.deleteCharAt(0);
}
return sb.toString();
}
String removeTrailingZeroes(String s) {
StringBuilder sb = new StringBuilder(s);
while (sb.length() > 0 && sb.charAt(sb.length() - 1) == '0') {
sb.setLength(sb.length() - 1);
}
return sb.toString();
}
Observe que usamosStringBuilder.setLength() em vez deStringBuilder.deleteCharAt() quando removemos os zeros à direita porque isso também exclui os últimos caracteres e tem mais desempenho.
Se nósdon’t want to return an empty String quando a entrada contém apenas zeros, a única coisa que precisamos fazer éstop the loop if there’s only a single character left.
Portanto, alteramos a condição do loop:
String removeLeadingZeroes(String s) {
StringBuilder sb = new StringBuilder(s);
while (sb.length() > 1 && sb.charAt(0) == '0') {
sb.deleteCharAt(0);
}
return sb.toString();
}
String removeTrailingZeroes(String s) {
StringBuilder sb = new StringBuilder(s);
while (sb.length() > 1 && sb.charAt(sb.length() - 1) == '0') {
sb.setLength(sb.length() - 1);
}
return sb.toString();
}
3. UsandoString.subString()
Nesta solução, quando removemos os zeros à esquerda ou à direita, nósfind the position of the first or last non-zero character.
Depois disso, só temos que chamarsubstring(), para retornar as partes restantes:
String removeLeadingZeroes(String s) {
int index;
for (index = 0; index < s.length(); index++) {
if (s.charAt(index) != '0') {
break;
}
}
return s.substring(index);
}
String removeTrailingZeroes(String s) {
int index;
for (index = s.length() - 1; index >= 0; index--) {
if (s.charAt(index) != '0') {
break;
}
}
return s.substring(0, index + 1);
}
Observe que temos que declarar a variávelindex antes do loop for porque queremos usar a variável fora do escopo do loop.
Observe também que temos que procurar caracteres diferentes de zero manualmente, já queString.indexOf()eString.lastIndexOf() funcionam apenas para correspondência exata.
Se nósdon’t want to return an empty String, temos que fazer a mesma coisa de antes:change the loop condition:
String removeLeadingZeroes(String s) {
int index;
for (index = 0; index < s.length() - 1; index++) {
if (s.charAt(index) != '0') {
break;
}
}
return s.substring(index);
}
String removeTrailingZeroes(String s) {
int index;
for (index = s.length() - 1; index > 0; index--) {
if (s.charAt(index) != '0') {
break;
}
}
return s.substring(0, index + 1);
}
4. Usando o Apache Commons
O Apache Commons possui muitas classes úteis, incluindoorg.apache.commons.lang.StringUtils. Para ser mais preciso, essa classe está no Apache Commons Lang3.
4.1. Dependências
Podemos usarApache Commons Lang3 inserindo esta dependência em nosso arquivopom.xml:
org.apache.commons
commons-lang3
3.8.1
4.2. Implementação
Na classeStringUtils, temos os métodosstripStart()estripEnd(). Eles removem caracteres iniciais e finais, respectivamente.
Como é exatamente o que precisamos, nossa solução é bastante simples:
String removeLeadingZeroes(String s) {
return StringUtils.stripStart(s, "0");
}
String removeTrailingZeroes(String s) {
return StringUtils.stripEnd(s, "0");
}
Infelizmente, não podemos configurar se queremos remover todas as ocorrências ou não. Portanto, precisamos controlá-lo manualmente.
Se a entrada não estava vazia, mas o strippedString está vazio, então temos que retornar exatamente um zero:
String removeLeadingZeroes(String s) {
String stripped = StringUtils.stripStart(s, "0");
if (stripped.isEmpty() && !s.isEmpty()) {
return "0";
}
return stripped;
}
String removeTrailingZeroes(String s) {
String stripped = StringUtils.stripEnd(s, "0");
if (stripped.isEmpty() && !s.isEmpty()) {
return "0";
}
return stripped;
}
Observe que esses métodos aceitamString como seu segundo parâmetro. EsteString representa um conjunto de caracteres, não uma sequência que desejamos remover.
Por exemplo, se passarmos“01”, eles removerão todos os caracteres iniciais ou finais, que são‘0' ou‘1'.
5. Usando goiaba
O Goiaba também fornece muitas classes de utilitários. Para este problema, podemos usarcom.google.common.base.CharMatcher, que fornece métodos utilitários para interagir com caracteres correspondentes.
5.1. Dependências
Para usar Guava, devemos adicionar o seguintedependencies ao nosso arquivopom.xml:
com.google.guava
guava
27.0.1-jre
Observe que se quisermos usar o Guava em um aplicativo Android, devemos usar a versão27.0-android.
5.2. Implementação
Em nosso caso, estamos interessados emtrimLeadingFrom() etrimTrailingFrom().
Como o nome sugere, eles removem qualquer caractere inicial ou final, respectivamente, deString, que corresponde aCharMatcher:
String removeLeadingZeroes(String s) {
return CharMatcher.is('0').trimLeadingFrom(s);
}
String removeTrailingZeroes(String s) {
return CharMatcher.is('0').trimTrailingFrom(s);
}
Eles têm as mesmas características, como os métodos Apache Commons que vimos.
Portanto, se não quisermos remover todos os zeros, podemos usar o mesmo truque:
String removeLeadingZeroes(String s) {
String stripped = CharMatcher.is('0').trimLeadingFrom(s);
if (stripped.isEmpty() && !s.isEmpty()) {
return "0";
}
return stripped;
}
String removeTrailingZeroes(String s) {
String stripped = CharMatcher.is('0').trimTrailingFrom(s);
if (stripped.isEmpty() && !s.isEmpty()) {
return "0";
}
return stripped;
}
Observe que comCharMatcher podemos criar regras de correspondência mais complexas.
6. Usando expressões regulares
Como nosso problema é um problema de correspondência de padrões, podemos usar expressões regulares:we want to match all zeroes at the beginning or the end de aString.
Além disso, queremos remover os zeros correspondentes. Em outras palavras, queremosreplace them with nothing, or in other words, an empty String.
Podemos fazer exatamente isso, com o métodoString.replaceAll():
String removeLeadingZeroes(String s) {
return s.replaceAll("^0+", "");
}
String removeTrailingZeroes(String s) {
return s.replaceAll("0+$", "");
}
Se não quisermos remover todos os zeros, poderíamos usar a mesma solução que usamos com Apache Commons e Guava. No entanto, existe uma forma de expressão regular pura para fazer isso: temos que fornecer um padrão, que não corresponda aString inteiro.
Dessa forma, se a entrada contiver apenas zeros, o mecanismo regexp manterá exatamente um fora da correspondência. Podemos fazer isso com os seguintes padrões:
String removeLeadingZeroes(String s) {
return s.replaceAll("^0+(?!$)", "");
}
String removeTrailingZeroes(String s) {
return s.replaceAll("(?!^)0+$", "");
}
Observe que“(?!^)” e“(?!$)” significa que não é o início ou o fim deString, respectivamente.
7. Conclusão
Neste tutorial, vimos várias maneiras de remover caracteres à esquerda e à direita de umString. A escolha entre essas implementações geralmente é simplesmente uma preferência pessoal.
Como de costume, os exemplos estão disponíveisover on GitHub.