1. StringTokenizeraula

E agora mais alguns cenários comuns envolvendo o trabalho com strings. Como dividir uma string em várias partes? Existem várias maneiras de fazer isso.

split()método

A primeira maneira de dividir uma string em várias partes é usar o split()método. Uma expressão regular que define uma string de delimitação especial deve ser passada como um argumento. Você aprenderá o que é uma expressão regular na missão Java Multithreading .

Exemplo:

Código Resultado
String str = "Good news everyone!";
String[] strings = str.split("ne");
System.out.println(Arrays.toString(strings));
O resultado será um array de três strings:
["Good ", "ws everyo", "!"]

Simples, mas às vezes essa abordagem é excessiva. Se houver muitos delimitadores (por exemplo, espaços, caracteres de nova linha, tabulações, pontos), será necessário construir uma expressão regular bastante complexa. É difícil de ler e, portanto, difícil de modificar.

StringTokenizeraula

Java tem uma classe especial cujo trabalho é dividir uma string em substrings.

Esta classe não usa expressões regulares: em vez disso, você simplesmente passa uma string que consiste em delimitadores. A vantagem dessa abordagem é que ela não quebra a corda inteira em pedaços de uma só vez, mas se move do começo ao fim, um passo de cada vez.

A classe tem um construtor e dois métodos importantes. Passamos ao construtor uma string que dividimos em partes e uma string composta por um conjunto de caracteres delimitadores.

Métodos Descrição
String nextToken()
Retorna a próxima substring
boolean hasMoreTokens()
Verifica se há mais substrings.

Essa classe lembra de alguma forma a classe Scanner, que também possui métodos nextLine()e hasNextLine().

Você pode criar um StringTokenizerobjeto com este comando:

StringTokenizer name = new StringTokenizer(string, delimiters);

Onde stringestá a string a ser dividida em partes. E delimitersé uma string e cada caractere nela é tratado como um delimitador. Exemplo:

Código Saída do console
String str = "Good news everyone!";

StringTokenizer tokenizer = new StringTokenizer(str,"ne");
while (tokenizer.hasMoreTokens())
{
   String token = tokenizer.nextToken();
   System.out.println(token);
}
Good 
ws 
v
ryo
!

Observe que cada caractere na string passado como a segunda string para o StringTokenizerconstrutor é considerado um separador.



2. String.format()método e StringFormatterclasse

Outro método interessante da classe String é format().

Digamos que você tenha várias variáveis ​​armazenando dados. Como você os exibe na tela em uma linha? Por exemplo, temos alguns dados (coluna da esquerda) e saída desejada (coluna da direita):

Código Saída do console
String name = "Amigo";
int age = 12;
String friend = "Diego";
int weight = 200;
User = {name: Amigo, age: 12 years, friend: Diego, weight: 200 kg.}

Seu código provavelmente ficará mais ou menos assim:

código do programa
String name = "Amigo";
int age = 12;
String friend = "Diego";
int weight = 200;

System.out.println("User = {name: " + name + ", age:" + age + " years, friend: " + friend+", weight: " + weight + " kg.}");

Esse código não é muito legível. E se os nomes das variáveis ​​fossem mais longos, o código se tornaria ainda mais difícil:

código do programa

class User {
    ......
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public List<String> getFriends() {
        return friends;
    }

    public ExtraInformation getExtraInformation() {
        return extraInformation;
    }
}

User user = new User();

System.out.println("User = {name: " + user.getName() + ", age:" + user.getAge() + " years, friend: " + user.getFriends().get(0) + ", weight: " + user.getExtraInformation().getWeight() + " kg.}");

Não é muito legível, não é?

Mas esta é uma situação comum em programas do mundo real, então quero falar sobre uma maneira de escrever este código de forma mais simples e concisa.

String.format

A classe String tem um format()método estático: permite especificar um padrão para montar uma string com dados. A aparência geral do comando é a seguinte:

String name = String.format(pattern, parameters);

Exemplo:

Código Resultado
String.format("Age=%d, Name=%s", age, name);
Age=12, Name=Amigo
String.format("Width=%d, Height=%d", width, height);
Width=20, Height=10
String.format("Fullname=%s", name);
Fullname=Diego

O format()primeiro parâmetro do método é uma string de formato que contém todo o texto desejado junto com caracteres especiais chamados especificadores de formato (como %de %s) nos locais onde você precisa inserir dados.

O format()método substitui esses %se %dos especificadores de formato pelos parâmetros que seguem a string de formato na lista de parâmetros. Se quisermos inserir uma string, escrevemos %s. Se quisermos inserir um número, o especificador de formato é %d. Exemplo:

Código Resultado
String s = String.format("a=%d, b=%d, c=%d", 1, 4, 3);
sé igual a"a=1, b=4, c=3"

Aqui está uma pequena lista de especificadores de formato que podem ser usados ​​dentro da string de formato:

especificador Significado
%s
String
%d
inteiro: byte, short, int,long
%f
número real: float,double
%b
boolean
%c
char
%t
Date
%%
%personagem

Esses especificadores indicam o tipo de dados, mas também existem especificadores que indicam a ordem dos dados. Para obter um argumento pelo seu número (a numeração começa em um), você precisa escrever " " em vez de " ". Exemplo:%1$d%d

Código Resultado
String s = String.format("a=%3$d, b=%2$d, c=%d", 11, 12, 13);
sé igual a"a=13, b=12, c=11"

%3$dobterá o terceiro argumento, %2$dobterá o segundo argumento e %dobterá o primeiro argumento. Os especificadores de formato %se %dreferem-se a argumentos independentemente de especificadores como %3$dou%2$s



3. Conjunto de Strings

Cada string especificada no código como uma string literal é armazenada em uma área da memória chamada StringPoolenquanto o programa está em execução. StringPoolé um array especial para armazenar strings. Sua finalidade é otimizar o armazenamento de strings:

Primeiro, as strings especificadas no código devem ser armazenadas em algum lugar, certo? O código consiste em comandos, mas os dados (especialmente strings grandes) devem ser armazenados na memória separadamente do código. Somente referências a objetos de string aparecem no código.

Em segundo lugar, todas as strings literais idênticas devem ser armazenadas na memória apenas uma vez. E é assim que funciona. Quando seu código de classe é carregado pela máquina Java, todas as strings literais são adicionadas ao StringPoolcaso ainda não estejam lá. Se eles já estiverem lá, simplesmente usamos uma referência de string do arquivo StringPool.

Da mesma forma, se você atribuir o mesmo literal a várias Stringvariáveis ​​em seu código, essas variáveis ​​conterão a mesma referência. Um literal será adicionado StringPoolapenas uma vez. Em todos os outros casos, o código obterá uma referência à string já carregada no arquivo StringPool.

Aqui está mais ou menos como funciona:

Código Trabalhando com o StringPool
String a = "Hello";
String b = "Hello";
String c = "Bye";
String[] pool = {"Hello", "Bye"};
a = pool[0];
b = pool[0];
c = pool[1];

É por isso que as variáveis a​​e birão armazenar as mesmas referências.

intern()método

E a melhor parte é que você pode adicionar programaticamente qualquer string ao arquivo StringPool. Para fazer isso, basta chamar o método Stringda variável intern().

O intern()método adicionará a string ao StringPoolse ainda não estiver lá e retornará uma referência à string no arquivo StringPool.

Se duas strings idênticas forem adicionadas ao StringPoolusando o intern()método, o método retornará a mesma referência. Isso pode ser usado para comparar strings por referência. Exemplo:

Código Observação
String a = new String("Hello");
String b = new String("Hello");
System.out.println(a == b);


false
String a = new String("Hello");
String b = new String("Hello");

String t1 = a.intern();
String t2 = b.intern();
System.out.println(a == b);
System.out.println(t1 == t2);





false
true

É improvável que você use esse método com frequência, mas as pessoas adoram perguntar sobre isso em entrevistas . Então é melhor saber do que não saber.