Recomendación de ID en Java: orden de normalización y truncamiento
La normalización de un ID depende del orden de las transformaciones. En particular, vuelve a quitar el punto final después de truncar a 15 caracteres. Quitar antes el punto final original no impide que el truncamiento exponga otro.
Las reglas del ejercicio normalizan las mayúsculas ASCII, conservan los caracteres permitidos y después tratan los puntos, el resultado vacío y la longitud en ese orden. Ambas soluciones suponen la entrada no null garantizada por el ejercicio. La solución Optional usa repeat() de Java 11 y ambas compilan para Java 11. Guarda una de las soluciones como Solution.java, sin poner las dos clases en el mismo archivo.
Flujo de procesamiento
El diagrama sigue la versión Optional. El bucle combina el filtrado y la reducción de puntos consecutivos, manteniendo las mismas reglas.
Conectar los pasos con Optional
import java.util.Locale;
import java.util.Optional;
public class Solution {
public String solution(String new_id) {
return Optional.of(new_id)
.map(s -> s.toLowerCase(Locale.ROOT))
.map(s -> s.replaceAll("[^a-z0-9._-]", ""))
.map(s -> s.replaceAll("[.]+", "."))
.map(s -> s.replaceAll("^[.]|[.]$", ""))
.map(s -> s.isEmpty() ? "a" : s)
.map(s -> s.length() > 15 ? s.substring(0, 15) : s)
.map(s -> s.replaceAll("[.]$", ""))
.map(s -> s.length() < 3
? s + s.substring(s.length() - 1).repeat(3 - s.length()) : s)
.orElseThrow();
}
}
Locale.ROOT evita que la conversión a minúsculas dependa de la configuración regional predeterminada. El patrón conserva solo letras ASCII minúsculas, dígitos, puntos, guiones bajos y guiones. Reduce los puntos consecutivos y elimina los de los extremos. Sustituye un resultado vacío por a, trunca a 15 caracteres, quita el punto final recién expuesto y repite el último carácter hasta alcanzar una longitud de 3.
Optional sirve para conectar transformaciones, sin ser una estructura de datos obligatoria. Optional.of rechaza null en lugar de tratarlo silenciosamente como un ID vacío.
Aplicar las mismas reglas con un bucle
Esta solución combina en una pasada el filtrado de caracteres permitidos y la eliminación de puntos consecutivos. Convertir solo las mayúsculas ASCII aprovecha el rango de entrada del ejercicio; no es una normalización general de nombres Unicode.
import java.util.Objects;
public class Solution {
public String solution(String new_id) {
Objects.requireNonNull(new_id);
StringBuilder result = new StringBuilder();
for (char input : new_id.toCharArray()) {
char c = input >= 'A' && input <= 'Z' ? (char) (input + 32) : input;
boolean allowed = (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9')
|| c == '-' || c == '_' || c == '.';
if (!allowed || (c == '.' && (result.length() == 0
|| result.charAt(result.length() - 1) == '.'))) continue;
result.append(c);
}
if (result.length() > 0 && result.charAt(result.length() - 1) == '.') {
result.setLength(result.length() - 1);
}
if (result.length() == 0) result.append('a');
if (result.length() > 15) result.setLength(15);
if (result.charAt(result.length() - 1) == '.') result.setLength(result.length() - 1);
while (result.length() < 3) result.append(result.charAt(result.length() - 1));
return result.toString();
}
}
| Entrada | Resultado | Regla comprobada |
|---|---|---|
=.= |
aaa |
Valor alternativo y relleno del resultado vacío |
z-+.^. |
z-- |
Caracteres permitidos y eliminación del punto final |
I |
iii |
Minúsculas independientes de la configuración regional |
abcdefghijklmn.op |
abcdefghijklmn |
Eliminación del punto expuesto al truncar |
Ambas soluciones tardan O(n) para una entrada de longitud n y usan O(n) de espacio adicional. La versión con expresiones regulares puede asignar varias cadenas intermedias, mientras que el bucle usa un StringBuilder. Sin mediciones, esto no demuestra que una sea siempre más rápida. Consulta la API String para la sustitución, la conversión a minúsculas y la repetición.
Para sustituciones literales de palabras de dígitos, consulta replace frente a replaceAll. Para claves de caché independientes de la configuración regional, consulta el ejemplo de caché LRU.
Comentarios