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.

Java SE 7

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.

Java SE 7

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.
}

Demo en vivo

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.
}

Demo en vivo

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

Demo en vivo


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

Java SE 7

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;
}

Demo en vivo

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 .

Java SE 7

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étodo String.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:

  1. Declara una cuerda.
  2. Introduzca la cadena.
  3. Convertir la cadena en una matriz de caracteres.
  4. Introduzca el carácter que se va a buscar.
  5. Busque el carácter en la matriz de caracteres.
  6. 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.
  7. Cambiar el carácter original de la matriz de caracteres.
  8. 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

Demo en vivo en Ideone


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

Demo en vivo en Ideone

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

Demo en vivo en Ideone

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

Demo en vivo en Ideone

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.

Java SE 7

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.

Java SE 7

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")
Java SE 7

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());

Demo en vivo en Ideone

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);

Demo en vivo en Ideone

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

Java SE 8

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.

  1. StringBuilder / StringBuffer:

     String code = "code";
     System.out.println(code);
    
     StringBuilder sb = new StringBuilder(code); 
     code = sb.reverse().toString();
    
     System.out.println(code);
    
  2. 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 a U+0020 se consideran espacios en blanco y se eliminan mediante trim() . Esto incluye los caracteres U+0020 'SPACE' , U+0009 'CHARACTER TABULATION' , U+000A 'LINE FEED' y U+000D 'CARRIAGE RETURN' , pero también los caracteres como U+0007 'BELL' .

  • Los espacios en blanco de Unicode, como U+00A0 'NO-BREAK SPACE' o U+2003 'EM SPACE' no son reconocidos por trim() .

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

Diagrama de Java Heap y String Pool 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.

Java SE 7

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 .

Java SE 7

RFC: 6962931

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

Java SE 7

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!


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow