Saludos
Al revisar el material acumulado, java.lang.String
decidí hacer una pequeña selección de ejemplos de uso efectivo (y no tan).
Cualquier conversión de línea genera una nueva línea
Este es uno de los principales mitos sobre las líneas. De hecho, este no es siempre el caso. Supongamos que tenemos una cadena que contiene solo letras minúsculas:
var str = "str";
Ahora este código
jshell> var str = "str";
jshell> System.out.println(str.toLowerCase() == str);
saldrá
true
En otras palabras, aquí la llamada toLowerCase()
devolvió la línea en la que se llamó. Y aunque este comportamiento no se describe en la documentación, el código StringLatin1.toLowerCase()
no deja dudas (aquí y abajo está el código de https://hg.openjdk.java.net/jdk/jdk/ ):
public static String toLowerCase(String str, byte[] value, Locale locale) {
if (locale == null) {
throw new NullPointerException();
}
int first;
final int len = value.length;
for (first = 0 ; first < len; first++) {
int cp = value[first] & 0xff;
if (cp != CharacterDataLatin1.instance.toLowerCase(cp)) {
break;
}
}
if (first == len)
return str;
}
: , . , , , String.trim()
String.strip()
:
public String trim() {
String ret = isLatin1() ? StringLatin1.trim(value)
: StringUTF16.trim(value);
return ret == null ? this : ret;
}
public String strip() {
String ret = isLatin1() ? StringLatin1.strip(value)
: StringUTF16.strip(value);
return ret == null ? this : ret;
}
:
boolean isUpperCase = name.toUpperCase().equals(name);
- StringUtils
, ( ""). / /, , name.toUpperCase()
name
, ?
boolean isUpperCase = name.toUpperCase() == name;
, , String.toUpperCase()
. ( , ) o.a.c.l.StringUtils.isAllUpperCase()
.
boolean eq = aString.toUpperCase().equals(anotherString);
boolean eq = aString.equalsIgnoreCase(anotherString);
, "" , "".
String.toLowerCase()
String.toLowerCase()
/ String.toUpperCase()
, . :
boolean isEmpty = someStr.toLowerCase().isEmpty();
, . , / . , isEmpty()
true
. false
, . . 1 , .
, :
boolean isEmpty = someStr.isEmpty();
. String.isEmpty()
:
public boolean isEmpty() {
return value.length == 0;
}
int len = someStr.toLowerCase().length();
int len = someStr.length();
, ?
String s = "!";
String s = "!";
, , . . — . , toLowerCase()
/ toUpperCase()
, . , . , :
@Test
void toLowerCase() {
String str = "\u00cc";
assert str.length() == 1;
String strLowerCase = str.toLowerCase(new Locale("lt"));
assert strLowerCase.length() == 3;
}
, : " ?" 1 , ( — 6 (!) ). :
public String toLowerCase(Locale locale) {
}
:
public static String toLowerCase(String str, byte[] value, Locale locale) {
String lang = locale.getLanguage();
if (lang == "tr" || lang == "az" || lang == "lt") {
return toLowerCaseEx(str, value, first, locale, true);
}
}
, , :)
1 — String.substring(n, n+1)
— , , , 1. :
boolean startsWithUnderline = message.substring(0, 1).equals("_");
boolean startsWithUnderline = message.charAt(0) == '_';
, . :
String s = "xxx" + name.substring(n, n + 1);
String s = "xxx" + name.charAt(n);
, . . . , .
— :
boolean startsWithUrl = content.substring(index, index + 4).equals("url(");
boolean startsWithUrl = content.startsWith("url(", index);
. , ( ):
private String findPerClause(String str) {
str = str.substring(str.indexOf('(') + 1);
str = str.substring(0, str.length() - 1);
return str;
}
, , :
( , )
-->
,
, , :
private String findPerClause(String str) {
int beginIndex = str.indexOf('(') + 1;
int endIndex = str.length() - 1;
return str.substring(beginIndex, endIndex);
}
, :
int idx = path.substring(2).indexOf('/');
, String.indexOf(int ch, int fromIndex)
, :
int idx = path.indexOf('/', 2);
. , '/'
2, . . :
int idx = name.indexOf('/', 2);
if (pos != -1) {
idx -= 2;
}
, .
JDK. ,
someStr.substring(n, n);
, n
:
public String substring(int beginIndex, int endIndex) {
int length = length();
checkBoundsBeginEnd(beginIndex, endIndex, length);
int subLen = endIndex - beginIndex;
if (beginIndex == 0 && endIndex == length) {
return this;
}
return isLatin1() ? StringLatin1.newString(value, beginIndex, subLen)
: StringUTF16.newString(value, beginIndex, subLen);
}
public static String newString(byte[] val, int index, int len) {
return new String(Arrays.copyOfRange(val, index, index + len), LATIN1);
}
beginIndex
endIndex
subLen
0, StringLatin1.newString()
. , :
public static String newString(byte[] val, int index, int len) {
if (len == 0) {
return "";
}
return new String(Arrays.copyOfRange(val, index, index + len), LATIN1);
}
StringLatin1.stripLeading() / stripTrailing()
StringUTF16
. .
, :
public static String stripLeading(byte[] value) {
int left = indexOfNonWhitespace(value);
if (left == value.length) {
return "";
}
return (left != 0) ? newString(value, left, value.length - left) : null;
}
value.length == 0
. left == value.length
newString
,
public static String stripLeading(byte[] value) {
int left = indexOfNonWhitespace(value);
return (left != 0) ? newString(value, left, value.length - left) : null;
}
null
! String.stripLeading()
, this
, . , . :
boolean b= new String("").stripLeading() == "";
boolean b= new String("").stripLeading() == "";
, ?
!
, :
@Warmup(iterations = 10, time = 1)
@Measurement(iterations = 10, time = 1)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(value = 3, jvmArgsAppend = {"-Xms4g", "-Xmx4g", "-XX:+UseParallelGC"})
public class SubstringBenchmark {
private static final String str = "Tolstoy";
@Benchmark
public String substring() {
return str.substring(1, 1);
}
}
:
Mode Score Error Units
substring avgt 5.8 ± 0.066 ns/op
substring:·gc.alloc.rate avgt 4325.9 ± 47.259 MB/sec
substring:·gc.alloc.rate.norm avgt 40.0 ± 0.001 B/op
substring:·gc.churn.G1_Eden_Space avgt 4338.8 ± 86.555 MB/sec
substring:·gc.churn.G1_Eden_Space.norm avgt 40.1 ± 0.647 B/op
substring:·gc.churn.G1_Survivor_Space avgt 0.0 ± 0.003 MB/sec
substring:·gc.churn.G1_Survivor_Space.norm avgt ≈ 10⁻⁴ B/op
substring:·gc.count avgt 557.0 counts
substring:·gc.time avgt 387.0 ms
substring avgt 2.4 ± 0.172 ns/op
substring:·gc.alloc.rate avgt 0.0 ± 0.001 MB/sec
substring:·gc.alloc.rate.norm avgt ≈ 10⁻⁵ B/op
substring:·gc.count avgt ≈ 0 counts
, String.substring(n, n)
, .
, , , , . , AnnotationMetadataReadingVisitor-:
MultiValueMap<String, Object> getAllAnnotationAttributes(String annotationName, boolean classValAsStr) {
String annotatedElement = "class '" + getClassName() + "'";
for (AnnotationAttributes raw : attributes) {
for (Map.Entry<String, Object> entry : convertClassValues(
"class '" + getClassName() + "'", classLoader, raw, classValAsStr).entrySet()) {
allAttributes.add(entry.getKey(), entry.getValue());
}
}
return allAttributes;
}
La expresión "class '" + getClassName() + "'"
será la misma y realmente no queremos crear la misma línea en un bucle doble, por lo que es mejor crearla 1 vez fuera del bucle. Anteriormente, la captura de tales ejemplos era una cuestión de azar: descubrí que este había fallado con éxito dentro de la fuente al depurar mi aplicación. Ahora, gracias a IDEA-230889, esto se puede automatizar. Por supuesto, está lejos de ser siempre la creación de una nueva línea en un bucle, independientemente del pasaje, pero incluso en estos casos, podemos distinguir aquellos en los que hay una parte constante duradera:
public static String uniqueBeanName(String beanName, BeanDefinitionRegistry registry) {
String id = beanName;
int counter = -1;
while (counter == -1 || registry.containsBeanDefinition(id)) {
counter++;
id = beanName + GENERATED_BEAN_NAME_SEPARATOR + counter;
}
return id;
}
Aquí el prefijo es beanName + GENERATED_BEAN_NAME_SEPARATOR
siempre la misma, para que pueda ser llevado a cabo.
Eso es todo, escriba sus ejemplos en los comentarios, lo cubriremos.