Java Language
Instrumentos de cuerda
Buscar..
Introducción
Las cadenas ( java.lang.String
) son fragmentos de texto almacenados en su programa. Las cadenas no son un tipo de datos primitivo en Java , sin embargo, son muy comunes en los programas Java.
En Java, las cadenas son inmutables, lo que significa que no se pueden cambiar. (Haga clic aquí para obtener una explicación más detallada de la inmutabilidad.)
Observaciones
Como las cadenas de Java son inmutables , todos los métodos que manipulen una String
devolverán un nuevo objeto de String
. No cambian la String
original. Esto incluye los métodos de subcadena y reemplazo que los programadores de C y C ++ esperan que muten el objeto String
destino.
Utilice un StringBuilder
lugar de String
si desea concatenar más de dos objetos String
cuyos valores no se pueden determinar en tiempo de compilación. Esta técnica es más eficaz que crear nuevos objetos String
y concatenarlos porque StringBuilder
es mutable.
StringBuffer
también se puede utilizar para concatenar objetos String
. Sin embargo, esta clase tiene menos rendimiento porque está diseñada para ser segura para subprocesos y adquiere un mutex antes de cada operación. Dado que casi nunca necesita seguridad para subprocesos al concatenar cadenas, es mejor usar StringBuilder
.
Si puede expresar una concatenación de cadenas como una sola expresión, entonces es mejor usar el operador +
. El compilador de Java convertirá una expresión que contenga +
concatenaciones en una secuencia eficiente de operaciones usando String.concat(...)
o StringBuilder
. El consejo para usar StringBuilder
solo se aplica explícitamente cuando la concatenación involucra expresiones múltiples.
No almacene información confidencial en cadenas. Si alguien puede obtener un volcado de memoria de su aplicación en ejecución, entonces podrá encontrar todos los objetos String
existentes y leer su contenido. Esto incluye los objetos de String
que son inalcanzables y están en espera de recolección de basura. Si esto es un problema, deberá borrar los datos confidenciales de las cadenas tan pronto como termine. No puedes hacer esto con objetos String
ya que son inmutables. Por lo tanto, es recomendable utilizar un objeto char[]
para contener datos de caracteres confidenciales y borrarlos (por ejemplo, sobrescribirlos con caracteres '\000'
) cuando haya terminado.
Todas las instancias de String
se crean en el montón, incluso las instancias que corresponden a literales de cadena. Lo especial de los literales de cadena es que la JVM garantiza que todos los literales que son iguales (es decir, que constan de los mismos caracteres) estén representados por un solo objeto de String
(este comportamiento se especifica en JLS). Esto es implementado por los cargadores de clases JVM. Cuando un cargador de clases carga una clase, explora los literales de cadena que se utilizan en la definición de la clase, cada vez que ve una, comprueba si ya existe un registro en el conjunto de cadenas para este literal (utilizando el literal como una clave) . Si ya existe una entrada para el literal, se usa la referencia a una instancia de String
almacenada como el par para ese literal. De lo contrario, se crea una nueva instancia de String
y se almacena una referencia a la instancia para el literal (utilizado como clave) en el conjunto de cadenas. (Véase también internado de cadena ).
El conjunto de cadenas se mantiene en el montón de Java y está sujeto a la recolección de elementos no utilizados normal.
En las versiones de Java anteriores a Java 7, el grupo de cadenas se mantuvo en una parte especial del montón conocido como "PermGen". Esta parte solo fue recogida ocasionalmente.
En Java 7, el grupo de cadenas se movió fuera de "PermGen".
Tenga en cuenta que los literales de cadena son implícitamente accesibles desde cualquier método que los use. Esto significa que los objetos String
correspondientes solo se pueden recolectar si el código en sí es recolectado.
Hasta que Java 8, los objetos String
se implementan como una matriz de caracteres UTF-16 (2 bytes por carácter). Hay una propuesta en Java 9 para implementar la String
como una matriz de bytes con un campo de marca de codificación para observar si la cadena está codificada como bytes (LATIN-1) o caracteres (UTF-16).
Comparando cuerdas
Con el fin de comparar las cadenas para la igualdad, debe utilizar los métodos equals
o equals
equalsIgnoreCase
.
Por ejemplo, el siguiente fragmento de código determinará si las dos instancias de String
son iguales en todos los caracteres:
String firstString = "Test123";
String secondString = "Test" + 123;
if (firstString.equals(secondString)) {
// Both Strings have the same content.
}
Este ejemplo los comparará, independientemente de su caso:
String firstString = "Test123";
String secondString = "TEST123";
if (firstString.equalsIgnoreCase(secondString)) {
// Both Strings are equal, ignoring the case of the individual characters.
}
Tenga en cuenta que equalsIgnoreCase
no le permite especificar una equalsIgnoreCase
Locale
. Por ejemplo, si comparas las dos palabras "Taki"
y "TAKI"
en inglés, son iguales; sin embargo, en turco son diferentes (en turco, la minúscula I
es ı
). Para casos como este, convertir ambas cadenas en minúsculas (o mayúsculas) con Locale
y luego compararlas con equals
es la solución.
String firstString = "Taki";
String secondString = "TAKI";
System.out.println(firstString.equalsIgnoreCase(secondString)); //prints true
Locale locale = Locale.forLanguageTag("tr-TR");
System.out.println(firstString.toLowerCase(locale).equals(
secondString.toLowerCase(locale))); //prints false
No use el operador == para comparar cadenas
A menos que pueda garantizar que todas las cadenas hayan sido internadas (ver más abajo), no debe usar los operadores ==
o !=
Para comparar cadenas. Estos operadores realmente prueban las referencias, y dado que varios objetos String
pueden representar el mismo String, esto puede dar una respuesta incorrecta.
En su lugar, use el String.equals(Object)
, que comparará los objetos String en función de sus valores. Para obtener una explicación detallada, consulte Pitfall: usar == para comparar cadenas .
Comparando cadenas en una instrucción switch
A partir de Java 1.7, es posible comparar una variable de cadena con literales en una instrucción de switch
. Asegúrese de que la Cadena no sea nula, de lo contrario siempre lanzará una NullPointerException
. Los valores se comparan utilizando String.equals
, es decir, String.equals
mayúsculas y minúsculas.
String stringToSwitch = "A";
switch (stringToSwitch) {
case "a":
System.out.println("a");
break;
case "A":
System.out.println("A"); //the code goes here
break;
case "B":
System.out.println("B");
break;
default:
break;
}
Comparando cadenas con valores constantes
Al comparar una String
con un valor constante, puede poner el valor constante en el lado izquierdo de equals
para asegurarse de que no obtendrá una excepción NullPointerException
si la otra cadena es null
.
"baz".equals(foo)
Mientras que foo.equals("baz")
lanzará una NullPointerException
si foo
es null
, "baz".equals(foo)
evaluará como false
.
Una alternativa más legible es usar Objects.equals()
, que realiza una comprobación nula de ambos parámetros: Objects.equals(foo, "baz")
.
( Nota: es discutible si es mejor evitar las NullPointerExceptions
en general, o dejar que ocurran y luego corregir la causa raíz; ver aquí y aquí . Ciertamente, calificar de "mejor práctica" a la estrategia de evitación no es justificable).
Ordenaciones de cuerdas
La clase String
implementa Comparable<String>
con el método String.compareTo
(como se describe al comienzo de este ejemplo). Esto hace que el orden natural de los objetos String
sea sensible a mayúsculas y minúsculas. La clase String
proporciona una constante Comparator<String>
denominada CASE_INSENSITIVE_ORDER
adecuada para una clasificación que no distingue entre mayúsculas y minúsculas.
Comparando con cuerdas internadas
La especificación del lenguaje Java ( JLS 3.10.6 ) establece lo siguiente:
"Además, un literal de cadena siempre se refiere a la misma instancia de la clase
String
. Esto se debe a que los literales de cadena, o, más generalmente, las cadenas que son valores de expresiones constantes, se internan para compartir instancias únicas, utilizando el métodoString.intern
".
Esto significa que es seguro comparar referencias a dos literales de cadena utilizando ==
. Además, lo mismo es cierto para las referencias a objetos String
que se han producido utilizando el método String.intern()
.
Por ejemplo:
String strObj = new String("Hello!");
String str = "Hello!";
// The two string references point two strings that are equal
if (strObj.equals(str)) {
System.out.println("The strings are equal");
}
// The two string references do not point to the same object
if (strObj != str) {
System.out.println("The strings are not the same object");
}
// If we intern a string that is equal to a given literal, the result is
// a string that has the same reference as the literal.
String internedStr = strObj.intern();
if (internedStr == str) {
System.out.println("The interned string and the literal are the same object");
}
Detrás de escena, el mecanismo de internado mantiene una tabla hash que contiene todas las cadenas internadas que aún son accesibles . Cuando llama a intern()
en una String
, el método busca el objeto en la tabla hash:
- Si se encuentra la cadena, ese valor se devuelve como la cadena internada.
- De lo contrario, se agrega una copia de la cadena a la tabla hash y esa cadena se devuelve como la cadena internada.
Es posible utilizar interning para permitir la comparación de cadenas utilizando ==
. Sin embargo, hay problemas significativos al hacer esto; Vea Pitfall - Interning Strings para que pueda usar == es una mala idea para obtener detalles. No se recomienda en la mayoría de los casos.
Cambiando el caso de los personajes dentro de una cadena
El tipo de String
proporciona dos métodos para convertir cadenas entre mayúsculas y minúsculas:
-
toUpperCase
para convertir todos los caracteres a mayúsculas -
toLowerCase
para convertir todos los caracteres a minúsculas
Estos dos métodos devuelven las cadenas convertidas como nuevas instancias de String
: los objetos de String
originales no se modifican porque la String
es inmutable en Java. Vea esto para más información sobre la inmutabilidad: Inmutabilidad de las cadenas en Java
String string = "This is a Random String";
String upper = string.toUpperCase();
String lower = string.toLowerCase();
System.out.println(string); // prints "This is a Random String"
System.out.println(lower); // prints "this is a random string"
System.out.println(upper); // prints "THIS IS A RANDOM STRING"
Los caracteres no alfabéticos, como los dígitos y los signos de puntuación, no se ven afectados por estos métodos. Tenga en cuenta que estos métodos también pueden tratar incorrectamente con ciertos caracteres Unicode bajo ciertas condiciones.
Nota : estos métodos son sensibles a la configuración regional y pueden producir resultados inesperados si se utilizan en cadenas que deben interpretarse independientemente de la configuración regional. Algunos ejemplos son los identificadores de lenguaje de programación, las claves de protocolo y las etiquetas HTML
.
Por ejemplo, "TITLE".toLowerCase()
en una configuración regional turca devuelve " tıtle
", donde ı (\u0131)
es el carácter LATIN SMALL LETTER DOTLESS I. Para obtener resultados correctos para las cadenas no sensibles al entorno local, pase Locale.ROOT
como parámetro al método de conversión de casos correspondiente (por ejemplo, toLowerCase(Locale.ROOT)
o toUpperCase(Locale.ROOT)
).
Aunque el uso de Locale.ENGLISH
también es correcto para la mayoría de los casos, el idioma invariable es Locale.ROOT
.
Puede encontrar una lista detallada de los caracteres Unicode que requieren una carcasa especial en el sitio web de Unicode Consortium .
Cambio de caso de un carácter específico dentro de una cadena ASCII:
Para cambiar el caso de un carácter específico de una cadena ASCII, se puede utilizar el siguiente algoritmo:
Pasos:
- Declara una cuerda.
- Introduzca la cadena.
- Convertir la cadena en una matriz de caracteres.
- Introduzca el carácter que se va a buscar.
- Busque el carácter en la matriz de caracteres.
- Si lo encuentra, verifique si el carácter está en minúscula o en mayúscula.
- Si está en mayúsculas, agregue 32 al código ASCII del carácter.
- Si es minúscula, resta 32 del código ASCII del carácter.
- Cambiar el carácter original de la matriz de caracteres.
- Convertir la matriz de caracteres de nuevo en la cadena.
Voila, se cambia el caso del personaje.
Un ejemplo del código para el algoritmo es:
Scanner scanner = new Scanner(System.in);
System.out.println("Enter the String");
String s = scanner.next();
char[] a = s.toCharArray();
System.out.println("Enter the character you are looking for");
System.out.println(s);
String c = scanner.next();
char d = c.charAt(0);
for (int i = 0; i <= s.length(); i++) {
if (a[i] == d) {
if (d >= 'a' && d <= 'z') {
d -= 32;
} else if (d >= 'A' && d <= 'Z') {
d += 32;
}
a[i] = d;
break;
}
}
s = String.valueOf(a);
System.out.println(s);
Encontrar una cadena dentro de otra cadena
Para verificar si una cadena en particular a
está contenida en una cadena b
o no, podemos usar el método String.contains()
con la siguiente sintaxis:
b.contains(a); // Return true if a is contained in b, false otherwise
El método String.contains()
se puede usar para verificar si se puede encontrar un CharSequence
en el String. El método busca la Cadena a
en la Cadena b
de manera sensible a las mayúsculas y minúsculas.
String str1 = "Hello World";
String str2 = "Hello";
String str3 = "helLO";
System.out.println(str1.contains(str2)); //prints true
System.out.println(str1.contains(str3)); //prints false
Para encontrar la posición exacta donde comienza una cadena dentro de otra cadena, use String.indexOf()
:
String s = "this is a long sentence";
int i = s.indexOf('i'); // the first 'i' in String is at index 2
int j = s.indexOf("long"); // the index of the first occurrence of "long" in s is 10
int k = s.indexOf('z'); // k is -1 because 'z' was not found in String s
int h = s.indexOf("LoNg"); // h is -1 because "LoNg" was not found in String s
El método String.indexOf()
devuelve el primer índice de un char
o String
en otra String
. El método devuelve -1
si no se encuentra.
Nota : el método String.indexOf()
mayúsculas y minúsculas.
Ejemplo de búsqueda ignorando el caso:
String str1 = "Hello World";
String str2 = "wOr";
str1.indexOf(str2); // -1
str1.toLowerCase().contains(str2.toLowerCase()); // true
str1.toLowerCase().indexOf(str2.toLowerCase()); // 6
Obtener la longitud de una cadena
Para obtener la longitud de un objeto String
, llame al método length()
. La longitud es igual al número de unidades de código UTF-16 (caracteres) en la cadena.
String str = "Hello, World!";
System.out.println(str.length()); // Prints out 13
Un char
en una cadena es el valor UTF-16. Los puntos de código Unicode cuyos valores son ≥ 0x1000 (por ejemplo, la mayoría de los emojis) usan dos posiciones char. Para contar el número de puntos de código Unicode en una cadena, independientemente de si cada punto de código se ajusta a un valor de char
UTF-16, puede usar el método codePointCount
:
int length = str.codePointCount(0, str.length());
También puede usar un flujo de puntos de código, a partir de Java 8:
int length = str.codePoints().count();
Subcadenas
String s = "this is an example";
String a = s.substring(11); // a will hold the string starting at character 11 until the end ("example")
String b = s.substring(5, 10); // b will hold the string starting at character 5 and ending right before character 10 ("is an")
String b = s.substring(5, b.length()-3); // b will hold the string starting at character 5 ending right before b' s lenght is out of 3 ("is an exam")
Las subcadenas también se pueden aplicar para dividir y agregar / reemplazar caracteres en su Cadena original. Por ejemplo, se enfrentó a una fecha china que contenía caracteres chinos, pero desea almacenarla como una cadena de fecha de formato correcto.
String datestring = "2015年11月17日"
datestring = datestring.substring(0, 4) + "-" + datestring.substring(5,7) + "-" + datestring.substring(8,10);
//Result will be 2015-11-17
El método de subcadena extrae una pieza de un String
. Cuando se proporciona un parámetro, el parámetro es el inicio y la pieza se extiende hasta el final de la String
. Cuando se dan dos parámetros, el primer parámetro es el carácter inicial y el segundo parámetro es el índice del carácter justo después del final (el carácter en el índice no está incluido). Una forma fácil de verificar es la resta del primer parámetro del segundo debe producir la longitud esperada de la cadena.
En las versiones JDK <7u6, el método de substring
crea una instancia de una String
que comparte el mismo char[]
respaldo char[]
que la String
original y tiene los campos internos de offset
y count
establecidos en el inicio y la longitud del resultado. Dicha compartición puede provocar pérdidas de memoria, que pueden evitarse llamando a la new String(s.substring(...))
para forzar la creación de una copia, después de lo cual el char[]
puede ser recolectado como basura.
Desde JDK 7u6, el método de la substring
siempre copia la matriz char[]
subyacente completa, haciendo que la complejidad sea lineal en comparación con la constante anterior pero garantizando la ausencia de pérdidas de memoria al mismo tiempo.
Obtención del personaje nth en una cadena
String str = "My String";
System.out.println(str.charAt(0)); // "M"
System.out.println(str.charAt(1)); // "y"
System.out.println(str.charAt(2)); // " "
System.out.println(str.charAt(str.length-1)); // Last character "g"
Para obtener el enésimo carácter de una cadena, simplemente llame a charAt(n)
en una String
, donde n
es el índice del carácter que desea recuperar
NOTA: el índice n
comienza en 0
, por lo que el primer elemento está en n = 0.
Plataforma independiente de nueva línea separadora.
Dado que el nuevo separador de línea varía de una plataforma a otra (por ejemplo, \n
en sistemas similares a Unix o \r\n
en Windows) a menudo es necesario tener una forma de acceso independiente de la plataforma. En Java se puede recuperar de una propiedad del sistema:
System.getProperty("line.separator")
Debido a que el nuevo separador de línea es tan comúnmente necesario, desde Java 7 en un método de acceso directo que devuelve exactamente el mismo resultado que el código anterior, está disponible:
System.lineSeparator()
Nota : ya que es muy poco probable que el nuevo separador de línea cambie durante la ejecución del programa, es una buena idea almacenarlo en una variable final estática en lugar de recuperarlo de la propiedad del sistema cada vez que sea necesario.
Cuando use String.format
, use %n
lugar de \n
o '\ r \ n' para generar un nuevo separador de línea independiente de la plataforma.
System.out.println(String.format('line 1: %s.%nline 2: %s%n', lines[0],lines[1]));
Añadiendo el método toString () para objetos personalizados
Supongamos que ha definido la siguiente clase de Person
:
public class Person {
String name;
int age;
public Person (int age, String name) {
this.age = age;
this.name = name;
}
}
Si creas un nuevo objeto Person
:
Person person = new Person(25, "John");
y más adelante en su código, use la siguiente declaración para imprimir el objeto:
System.out.println(person.toString());
Obtendrá una salida similar a la siguiente:
Person@7ab89d
Este es el resultado de la implementación del método toString()
definido en la clase Object
, una superclase de Person
. La documentación de Object.toString()
establece:
El método toString para la clase Object devuelve una cadena que consiste en el nombre de la clase de la que el objeto es una instancia, el carácter de signo at '@' y la representación hexadecimal sin signo del código hash del objeto. En otras palabras, este método devuelve una cadena igual al valor de:
getClass().getName() + '@' + Integer.toHexString(hashCode())
Por lo tanto, para obtener resultados significativos, deberá anular el método toString()
:
@Override
public String toString() {
return "My name is " + this.name + " and my age is " + this.age;
}
Ahora la salida será:
My name is John and my age is 25
También puedes escribir
System.out.println(person);
De hecho, println()
invoca implícitamente el método toString
en el objeto.
Dividir cuerdas
Puede dividir una String
en un carácter delimitador particular o una expresión regular , puede usar el método String.split()
que tiene la siguiente firma:
public String[] split(String regex)
Tenga en cuenta que el carácter delimitado o la expresión regular se eliminan de la matriz de cadenas resultante.
Ejemplo usando caracteres delimitadores:
String lineFromCsvFile = "Mickey;Bolton;12345;121216";
String[] dataCells = lineFromCsvFile.split(";");
// Result is dataCells = { "Mickey", "Bolton", "12345", "121216"};
Ejemplo usando expresión regular:
String lineFromInput = "What do you need from me?";
String[] words = lineFromInput.split("\\s+"); // one or more space chars
// Result is words = {"What", "do", "you", "need", "from", "me?"};
Incluso puedes dividir directamente un literal de String
:
String[] firstNames = "Mickey, Frank, Alicia, Tom".split(", ");
// Result is firstNames = {"Mickey", "Frank", "Alicia", "Tom"};
Advertencia : No olvide que el parámetro siempre se trata como una expresión regular.
"aaa.bbb".split("."); // This returns an empty array
En el ejemplo anterior .
se trata como el comodín de expresión regular que coincide con cualquier carácter, y como cada carácter es un delimitador, el resultado es una matriz vacía.
División basada en un delimitador que es un meta-carácter de expresiones regulares
Los siguientes caracteres se consideran especiales (también conocidos como meta-caracteres) en expresiones regulares
< > - = ! ( ) [ ] { } \ ^ $ | ? * + .
Para dividir una cadena basada en uno de los delimitadores anteriores, necesita escapar de ellos usando \\
o usar Pattern.quote()
:
Utilizando
Pattern.quote()
:String s = "a|b|c"; String regex = Pattern.quote("|"); String[] arr = s.split(regex);
Escapar de los caracteres especiales:
String s = "a|b|c"; String[] arr = s.split("\\|");
La división elimina los valores vacíos
split(delimiter)
de forma predeterminada elimina las cadenas vacías finales de la matriz de resultados. Para desactivar este mecanismo, necesitamos usar una versión sobrecargada de split(delimiter, limit)
con límite establecido en valor negativo como
String[] split = data.split("\\|", -1);
split(regex)
devuelve internamente el resultado de split(regex, 0)
.
El parámetro límite controla el número de veces que se aplica el patrón y, por lo tanto, afecta la longitud de la matriz resultante.
Si el límite n es mayor que cero, entonces el patrón se aplicará a lo sumo n - 1 veces, la longitud de la matriz no será mayor que n , y la última entrada de la matriz contendrá toda la entrada más allá del último delimitador coincidente.
Si n es negativo, entonces el patrón se aplicará tantas veces como sea posible y la matriz puede tener cualquier longitud.
Si n es cero, el patrón se aplicará tantas veces como sea posible, la matriz puede tener cualquier longitud y las cadenas vacías finales se descartarán.
Dividir con un StringTokenizer
Además del método split()
, las cadenas también se pueden dividir utilizando un StringTokenizer
.
StringTokenizer
es incluso más restrictivo que String.split()
, y también un poco más difícil de usar. Básicamente, está diseñado para extraer tokens delimitados por un conjunto fijo de caracteres (dados como una String
). Cada personaje actuará como separador. Debido a esta restricción, es aproximadamente el doble de rápido que String.split()
.
El conjunto predeterminado de caracteres son espacios vacíos ( \t\n\r\f
). El siguiente ejemplo imprimirá cada palabra por separado.
String str = "the lazy fox jumped over the brown fence";
StringTokenizer tokenizer = new StringTokenizer(str);
while (tokenizer.hasMoreTokens()) {
System.out.println(tokenizer.nextToken());
}
Esto imprimirá:
the
lazy
fox
jumped
over
the
brown
fence
Puedes usar diferentes juegos de caracteres para la separación.
String str = "jumped over";
// In this case character `u` and `e` will be used as delimiters
StringTokenizer tokenizer = new StringTokenizer(str, "ue");
while (tokenizer.hasMoreTokens()) {
System.out.println(tokenizer.nextToken());
}
Esto imprimirá:
j
mp
d ov
r
Uniendo cuerdas con un delimitador
Una matriz de cadenas se puede unir usando el método estático String.join()
:
String[] elements = { "foo", "bar", "foobar" };
String singleString = String.join(" + ", elements);
System.out.println(singleString); // Prints "foo + bar + foobar"
De manera similar, hay un String.join()
sobrecargado de String.join()
para Iterable
s.
Para tener un control preciso sobre las uniones , puede usar la clase StringJoiner :
StringJoiner sj = new StringJoiner(", ", "[", "]");
// The last two arguments are optional,
// they define prefix and suffix for the result string
sj.add("foo");
sj.add("bar");
sj.add("foobar");
System.out.println(sj); // Prints "[foo, bar, foobar]"
Para unir un flujo de cadenas, puede utilizar el recopilador de unión :
Stream<String> stringStream = Stream.of("foo", "bar", "foobar");
String joined = stringStream.collect(Collectors.joining(", "));
System.out.println(joined); // Prints "foo, bar, foobar"
Hay una opción para definir prefijo y sufijo aquí también:
Stream<String> stringStream = Stream.of("foo", "bar", "foobar");
String joined = stringStream.collect(Collectors.joining(", ", "{", "}"));
System.out.println(joined); // Prints "{foo, bar, foobar}"
Cuerdas de inversión
Hay un par de maneras en que puedes revertir una cadena para hacerla al revés.
StringBuilder / StringBuffer:
String code = "code"; System.out.println(code); StringBuilder sb = new StringBuilder(code); code = sb.reverse().toString(); System.out.println(code);
Matriz de caracteres:
String code = "code"; System.out.println(code); char[] array = code.toCharArray(); for (int index = 0, mirroredIndex = array.length - 1; index < mirroredIndex; index++, mirroredIndex--) { char temp = array[index]; array[index] = array[mirroredIndex]; array[mirroredIndex] = temp; } // print reversed System.out.println(new String(array));
Contar las apariciones de una subcadena o carácter en una cadena
countMatches
método countMatches
de org.apache.commons.lang3.StringUtils se usa normalmente para contar las ocurrencias de una subcadena o un carácter en una String
:
import org.apache.commons.lang3.StringUtils;
String text = "One fish, two fish, red fish, blue fish";
// count occurrences of a substring
String stringTarget = "fish";
int stringOccurrences = StringUtils.countMatches(text, stringTarget); // 4
// count occurrences of a char
char charTarget = ',';
int charOccurrences = StringUtils.countMatches(text, charTarget); // 3
De lo contrario, para lo mismo con las API de Java estándar, puede usar expresiones regulares:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
String text = "One fish, two fish, red fish, blue fish";
System.out.println(countStringInString("fish", text)); // prints 4
System.out.println(countStringInString(",", text)); // prints 3
public static int countStringInString(String search, String text) {
Pattern pattern = Pattern.compile(search);
Matcher matcher = pattern.matcher(text);
int stringOccurrences = 0;
while (matcher.find()) {
stringOccurrences++;
}
return stringOccurrences;
}
Concatenación de cadenas y StringBuilders
La concatenación de cadenas se puede realizar con el operador +
. Por ejemplo:
String s1 = "a";
String s2 = "b";
String s3 = "c";
String s = s1 + s2 + s3; // abc
Normalmente, una implementación del compilador realizará la concatenación anterior utilizando métodos que involucren un StringBuilder
debajo del capó. Cuando se compila, el código sería similar al siguiente:
StringBuilder sb = new StringBuilder("a");
String s = sb.append("b").append("c").toString();
StringBuilder
tiene varios métodos sobrecargados para agregar diferentes tipos, por ejemplo, para agregar un int
lugar de una String
. Por ejemplo, una implementación puede convertir:
String s1 = "a";
String s2 = "b";
String s = s1 + s2 + 2; // ab2
a lo siguiente:
StringBuilder sb = new StringBuilder("a");
String s = sb.append("b").append(2).toString();
Los ejemplos anteriores ilustran una operación de concatenación simple que se realiza efectivamente en un solo lugar en el código. La concatenación involucra una sola instancia del StringBuilder
. En algunos casos, una concatenación se lleva a cabo de forma acumulativa, como en un bucle:
String result = "";
for(int i = 0; i < array.length; i++) {
result += extractElement(array[i]);
}
return result;
En tales casos, la optimización del compilador generalmente no se aplica, y cada iteración creará un nuevo objeto StringBuilder
. Esto se puede optimizar al transformar explícitamente el código para usar un único StringBuilder
:
StringBuilder result = new StringBuilder();
for(int i = 0; i < array.length; i++) {
result.append(extractElement(array[i]));
}
return result.toString();
Un StringBuilder
se inicializará con un espacio vacío de solo 16 caracteres. Si sabe de antemano que construirá cadenas más grandes, puede ser beneficioso inicializarlo con suficiente tamaño por adelantado, de modo que no sea necesario cambiar el tamaño del búfer interno:
StringBuilder buf = new StringBuilder(30); // Default is 16 characters
buf.append("0123456789");
buf.append("0123456789"); // Would cause a reallocation of the internal buffer otherwise
String result = buf.toString(); // Produces a 20-chars copy of the string
Si está produciendo muchas cadenas, es recomendable reutilizar StringBuilder
s:
StringBuilder buf = new StringBuilder(100);
for (int i = 0; i < 100; i++) {
buf.setLength(0); // Empty buffer
buf.append("This is line ").append(i).append('\n');
outputfile.write(buf.toString());
}
Si (y solo si) múltiples hilos están escribiendo en el mismo búfer, use StringBuffer , que es una versión synchronized
de StringBuilder
. Pero debido a que normalmente solo un único hilo escribe en un búfer, usualmente es más rápido usar StringBuilder
sin sincronización.
Utilizando el método concat ():
String string1 = "Hello ";
String string2 = "world";
String string3 = string1.concat(string2); // "Hello world"
Esto devuelve una nueva cadena que es string1 con string2 agregada al final. También puedes usar el método concat () con cadenas literales, como en:
"My name is ".concat("Buyya");
Reemplazo de partes de cuerdas
Dos formas de reemplazar: por expresiones regulares o por coincidencia exacta.
Nota: el objeto String original no se modificará, el valor de retorno conserva la String modificada.
Coincidencia exacta
Reemplazar el carácter único con otro carácter único:
String replace(char oldChar, char newChar)
Devuelve una nueva cadena resultante de reemplazar todas las apariciones de oldChar en esta cadena con newChar.
String s = "popcorn";
System.out.println(s.replace('p','W'));
Resultado:
WoWcorn
Reemplace la secuencia de caracteres con otra secuencia de caracteres:
String replace(CharSequence target, CharSequence replacement)
Reemplaza cada subcadena de esta cadena que coincida con la secuencia de destino literal con la secuencia de reemplazo literal especificada.
String s = "metal petal et al.";
System.out.println(s.replace("etal","etallica"));
Resultado:
metallica petallica et al.
Regex
Nota : la agrupación utiliza el carácter $
para hacer referencia a los grupos, como $1
.
Reemplazar todos los partidos:
String replaceAll(String regex, String replacement)
Reemplaza cada subcadena de esta cadena que coincide con la expresión regular dada con el reemplazo dado.
String s = "spiral metal petal et al.";
System.out.println(s.replaceAll("(\\w*etal)","$1lica"));
Resultado:
spiral metallica petallica et al.
Reemplazar solo el primer partido:
String replaceFirst(String regex, String replacement)
Reemplaza la primera subcadena de esta cadena que coincide con la expresión regular dada con el reemplazo dado
String s = "spiral metal petal et al.";
System.out.println(s.replaceAll("(\\w*etal)","$1lica"));
Resultado:
spiral metallica petal et al.
Eliminar espacios en blanco desde el principio y el final de una cadena
El método trim()
devuelve una nueva Cadena con los espacios en blanco iniciales y finales eliminados.
String s = new String(" Hello World!! ");
String t = s.trim(); // t = "Hello World!!"
Si trim
una cadena que no tiene espacios en blanco para eliminar, se le devolverá la misma instancia de cadena.
Tenga en cuenta que el método trim()
tiene su propia noción de espacio en blanco , que difiere de la noción utilizada por el método Character.isWhitespace()
:
Todos los caracteres de control ASCII con los códigos
U+0000
aU+0020
se consideran espacios en blanco y se eliminan mediantetrim()
. Esto incluye los caracteresU+0020 'SPACE'
,U+0009 'CHARACTER TABULATION'
,U+000A 'LINE FEED'
yU+000D 'CARRIAGE RETURN'
, pero también los caracteres comoU+0007 'BELL'
.Los espacios en blanco de Unicode, como
U+00A0 'NO-BREAK SPACE'
oU+2003 'EM SPACE'
no son reconocidos portrim()
.
Cadena de almacenamiento y almacenamiento en montón
Al igual que muchos objetos Java, todas las instancias de String
se crean en el montón, incluso literales. Cuando la JVM encuentra un literal de String
que no tiene una referencia equivalente en el montón, la JVM crea una instancia de String
correspondiente en el montón y también almacena una referencia a la instancia de String
recién creada en el conjunto de cadenas. Cualquier otra referencia al mismo literal de String
se reemplaza con la instancia de String
creada anteriormente en el montón.
Veamos el siguiente ejemplo:
class Strings
{
public static void main (String[] args)
{
String a = "alpha";
String b = "alpha";
String c = new String("alpha");
//All three strings are equivalent
System.out.println(a.equals(b) && b.equals(c));
//Although only a and b reference the same heap object
System.out.println(a == b);
System.out.println(a != c);
System.out.println(b != c);
}
}
La salida de lo anterior es:
true
true
true
true
Cuando usamos comillas dobles para crear una Cadena, primero busca Cadena con el mismo valor en el conjunto de Cadenas, si se encuentra, simplemente devuelve la referencia, sino que crea una nueva Cadena en el conjunto y luego devuelve la referencia.
Sin embargo, al utilizar un nuevo operador, obligamos a la clase String a crear un nuevo objeto String en el espacio de almacenamiento dinámico. Podemos usar el método intern () para ponerlo en el grupo o referirnos a otro objeto String del grupo de cadenas que tenga el mismo valor.
El conjunto de cadenas en sí también se crea en el montón.
Antes de Java 7, los literales de String
se almacenaban en el grupo de constantes de tiempo de ejecución en el área de método de PermGen
, que tenía un tamaño fijo.
El grupo de cuerdas también residía en PermGen
.
En JDK 7, las cadenas internas ya no se asignan en la generación permanente del montón de Java, sino que se asignan en la parte principal del montón de Java (conocidas como generaciones jóvenes y viejas), junto con los otros objetos creados por la aplicación . Este cambio dará como resultado que más datos residan en el montón principal de Java y menos datos en la generación permanente, por lo que es posible que sea necesario ajustar los tamaños del montón. La mayoría de las aplicaciones solo verán diferencias relativamente pequeñas en el uso del montón debido a este cambio, pero las aplicaciones más grandes que cargan muchas clases o hacen un uso intensivo del método
String.intern()
verán diferencias más significativas.
Interruptor insensible a la caja
switch
sí no se puede parametrizar para que no distinga mayúsculas de minúsculas, pero si es absolutamente necesario, puede comportarse de manera insensible a la cadena de entrada utilizando toLowerCase()
o toUpperCase
:
switch (myString.toLowerCase()) {
case "case1" :
...
break;
case "case2" :
...
break;
}
Tener cuidado
-
Locale
puede afectar cómo suceden los casos cambiantes ! - Se debe tener cuidado de no tener caracteres en mayúscula en las etiquetas, ¡nunca se ejecutarán!