jueves, 11 de mayo de 2023

String Interpolation en Java


La interpolación de cadenas es una forma sencilla y precisa de inyectar valores variables en una cadena. Permite a los usuarios incrustar referencias de variables directamente en literales de cadena procesados. Java carece de soporte nativo para la interpolación de cadenas en comparación con lenguajes como Scala.

Sin embargo, existen algunos enfoques para lograr este comportamiento en Java.

Primero, tenemos el operador "+". Podemos usar el operador "+" para concatenar nuestras variables y valores de cadena. La variable se reemplaza por su valor, por lo que logramos la interpolación o concatenación de cadenas:


@Test

public void givenTwoString_thenInterpolateWithPlusSign() {

    String EXPECTED_STRING = "String Interpolation in Java with some Java examples.";

    String first = "Interpolation";

    String second = "Java";

    String result = "String " + first + " in " + second + " with some " + second + " examples.";

    assertEquals(EXPECTED_STRING, result);

}


Como podemos ver en el ejemplo anterior, con este operador el String resultante contiene los valores de las variables “interpolados” con otros valores de string. Dado que puede ajustarse para satisfacer necesidades específicas, este método de concatenación de cadenas se encuentra entre los más sencillos y valiosos. Cuando usamos el operador, no necesitamos poner el texto entre comillas.

Otro enfoque es usar el método format() de la clase String. Al contrario del operador "+", en este caso necesitamos usar marcadores de posición para obtener el resultado esperado en la interpolación de cadenas:

@Test

public void givenTwoString_thenInterpolateWithFormat() {

    String EXPECTED_STRING = "String Interpolation in Java with some Java examples.";

    String first = "Interpolation";

    String second = "Java";

    String result = String.format("String %s in %s with some %s examples.", first, second, second);

    assertEquals(EXPECTED_STRING, result);

}

Además, podemos hacer referencia a un argumento específico si queremos evitar repeticiones de variables en nuestra llamada de formato:

@Test

public void givenTwoString_thenInterpolateWithFormatStringReference() {

    String EXPECTED_STRING = "String Interpolation in Java with some Java examples.";

    String first = "Interpolation";

    String second = "Java";

    String result = String.format("String %1$s in %2$s with some %2$s examples.", first, second);

    assertEquals(EXPECTED_STRING, result);

}

Nuestro siguiente enfoque es la clase StringBuilder. Instanciamos un objeto StringBuilder y luego llamamos a la función append() para construir el String. En el proceso, nuestras variables se agregan a la cadena resultante:


@Test

public void givenTwoString_thenInterpolateWithStringBuilder() {

    String EXPECTED_STRING = "String Interpolation in Java with some Java examples.";

    String first = "Interpolation";

    String second = "Java";

    StringBuilder builder = new StringBuilder();

    builder.append("String ")

      .append(first)

      .append(" in ")

      .append(second)

      .append(" with some ")

      .append(second)

      .append(" examples.");

    String result = builder.toString();

    assertEquals(EXPECTED_STRING, result);

}


Como podemos ver en el ejemplo de código anterior, podemos interpolar las cadenas con el texto necesario encadenando la función de agregar, que acepta el parámetro como una variable (en este caso, dos cadenas).

El uso de la clase MessageFormat es un método menos conocido para obtener la interpolación de cadenas en Java. Con MessageFormat, podemos crear mensajes concatenados sin preocuparnos por el idioma subyacente. Es un método estándar para crear mensajes orientados al usuario. Toma una colección de objetos, formatea las cadenas contenidas dentro y las inserta en el patrón en las ubicaciones adecuadas.

El método de formato de MessageFormat es casi idéntico al método de formato de String, excepto por cómo se escriben los marcadores de posición. Índices como {0}, {1}, {2}, etc., representan el marcador de posición en esta función:


@Test

public void givenTwoString_thenInterpolateWithMessageFormat() {

    String EXPECTED_STRING = "String Interpolation in Java with some Java examples.";

    String first = "Interpolation";

    String second = "Java";

    String result = MessageFormat.format("String {0} in {1} with some {1} examples.", first, second);

    assertEquals(EXPECTED_STRING, result);

}

En cuanto al rendimiento, StringBuilder solo agrega texto a un búfer dinámico; sin embargo, MessageFormat analiza el formato dado antes de agregar los datos. Como resultado, StringBuilder supera a MessageFormat en términos de eficiencia.

Finalmente, tenemos StringSubstitutor de Apache Commons. En el contexto de esta clase, los valores se sustituyen por variables incluidas dentro de una Cadena. Esta clase toma un fragmento de texto y reemplaza todas las variables. La definición predeterminada de una variable es ${variableName}. Se pueden usar constructores y métodos de conjuntos para modificar el prefijo y los sufijos. La resolución de los valores de las variables normalmente implica el uso de un mapa. Sin embargo, podemos resolverlos utilizando los atributos del sistema o proporcionando un solucionador de variables especializado:

@Test

public void givenTwoString_thenInterpolateWithStringSubstitutor() {

    String EXPECTED_STRING = "String Interpolation in Java with some Java examples.";

    String baseString = "String ${first} in ${second} with some ${second} examples.";

    String first = "Interpolation";

    String second = "Java";

    Map<String, String> parameters = new HashMap<>();

    parameters.put("first", first);

    parameters.put("second", second);

    StringSubstitutor substitutor = new StringSubstitutor(parameters);

    String result = substitutor.replace(baseString);

    assertEquals(EXPECTED_STRING, result);

}

De nuestro ejemplo de código, podemos ver que creamos un Map. Los nombres de las claves son los mismos que los nombres de las variables que reemplazaremos en el String. Luego pondremos el valor correspondiente para cada clave en el Map. A continuación, lo pasaremos como argumento constructor a la clase StringSubstitutor. Finalmente, el objeto instanciado llama a la función replace(). Esta función recibe como argumento el texto con los marcadores de posición. Como resultado, obtenemos un texto interpolado.

Como vemos no es tarea fácil interpolar strings en java actualmente, pero tenemos la esperanza que en java 21 vendrá string template. Esta funcionalidad nos permitirá hacer lo siguiente : 

String name = "Joan";

String info = STR."My name is \{name}";

assert info.equals("My name is Joan");   // true

Otro ejemplo puede ser : 

// Embedded expressions can be strings

String firstName = "Bill";

String lastName  = "Duck";

String fullName  = STR."\{firstName} \{lastName}"; // "Bill Duck"

String sortName  = STR."\{lastName}, \{firstName}"; // "Duck, Bill"

// Embedded expressions can perform arithmetic

int x = 10, y = 20;

String s = STR."\{x} + \{y} = \{x + y}"; // "10 + 20 = 30"

Que opinan?


Dejo link: https://openjdk.org/jeps/430



No hay comentarios.:

Publicar un comentario