Java.lang.String рдХреА рдЫреЛрдЯреА рд╕реВрдХреНрд╖реНрдорддрд╛рдПрдБ

рдЕрднрд┐рд╡рд╛рджрди


рд╕рдВрдЪрд┐рдд рд╕рд╛рдордЧреНрд░реА рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЬрд╛рдиреЗ рдкрд░, java.lang.StringрдореИрдВрдиреЗ рдкреНрд░рднрд╛рд╡реА (рдФрд░ рдРрд╕рд╛ рдирд╣реАрдВ) рдЙрдкрдпреЛрдЧ рд╕реЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХрд╛ рдПрдХ рдЫреЛрдЯрд╛ рдЪрдпрди рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред


рдХреЛрдИ рднреА рд▓рд╛рдЗрди рд░реВрдкрд╛рдВрддрд░рдг рдПрдХ рдирдИ рд▓рд╛рдЗрди рдмрдирд╛рддрд╛ рд╣реИ


рдпрд╣ рд▓рд╛рдЗрдиреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдореБрдЦреНрдп рдорд┐рдердХреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рд╣реИред рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ, рдпрд╣ рд╣рдореЗрд╢рд╛ рдорд╛рдорд▓рд╛ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИред рдорд╛рди рд▓реЗрдВ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдПрдХ рд╕реНрдЯреНрд░рд┐рдВрдЧ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рдХреЗрд╡рд▓ рд▓реЛрдЕрд░рдХреЗрд╕ рдЕрдХреНрд╖рд░ рд╣реИрдВ:


var str = "str";

рдЕрдм рдпрд╣ рдХреЛрдб


jshell> var str = "str";
jshell> System.out.println(str.toLowerCase() == str);

рдЙрддреНрдкрд╛рджрди рд╣реЛрдЧрд╛


true

рджреВрд╕рд░реЗ рд╢рдмреНрджреЛрдВ рдореЗрдВ, рдпрд╣рд╛рдБ рдХреЙрд▓ toLowerCase()рдиреЗ рдЙрд╕ рд▓рд╛рдЗрди рдХреЛ рд▓реМрдЯрд╛ рджрд┐рдпрд╛ рдЬрд┐рд╕ рдкрд░ рдЙрд╕реЗ рдмреБрд▓рд╛рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдФрд░ рд╣рд╛рд▓рд╛рдВрдХрд┐ рдЗрд╕ рд╡реНрдпрд╡рд╣рд╛рд░ рдХрд╛ рджрд╕реНрддрд╛рд╡реЗрдЬрд╝реАрдХрд░рдг рдореЗрдВ рд╡рд░реНрдгрди рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ, рдХреЛрдб StringLatin1.toLowerCase()рдХреЛ рдХреЛрдИ рд╕рдВрджреЗрд╣ рдирд╣реАрдВ рд╣реИ (рдпрд╣рд╛рдВ рдФрд░ рдиреАрдЪреЗ 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;
  // Now check if there are any characters that need to be changed
  for (first = 0 ; first < len; first++) {
    int cp = value[first] & 0xff;
    // no need to check Character.ERROR
    if (cp != CharacterDataLatin1.instance.toLowerCase(cp)) {
      break;
    }
  }
  if (first == len)
    return str;     // <--   this
  //...
}

: , . , , , String.trim() String.strip():


//  :    strip()
//  trim()    this

/**
 *
 * @return  a string whose value is this string, with all leading
 *          and trailing space removed, or this string if it
 *          has no leading or trailing space.
 */
public String trim() {
  String ret = isLatin1() ? StringLatin1.trim(value)
                          : StringUTF16.trim(value);
  return ret == null ? this : ret;
}

/**
 * @return  a string whose value is this string, with all leading
 *          and trailing white space removed
 *
 * @see Character#isWhitespace(int)
 *
 * @since 11
 */
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; // i╠З╠А
}

, : " ?" 1 , ( тАФ 6 (!) ). :


/**
 * Converts all of the characters in this {@code String} to lower
 * case using the rules of the given {@code Locale}.  Case mapping is based
 * on the Unicode Standard version specified by the {@link java.lang.Character Character}
 * class. Since case mappings are not always 1:1 char mappings, the resulting
 * {@code String} may be a different length than the original {@code String}.
 */
public String toLowerCase(Locale locale) {
  //...
}

:


//StringLatin1

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 :


// String

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

// StringLatin1

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() . , :


// StringLatin1

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


, :


//  StringLatin1  
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() == ""; // true

//  
boolean b= new String("").stripLeading() == ""; // false !

, ?


, :)
рд╕рдВрдЧрддрддрд╛ рдХреЗ рджреГрд╖реНрдЯрд┐рдХреЛрдг рд╕реЗ, рдореБрдЭреЗ рд▓рдЧрддрд╛ рд╣реИ рдХрд┐ рдпрд╣ рдареАрдХ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП, рдХреНрдпреЛрдВрдХрд┐
рд▓реМрдЯреА рд╣реБрдИ рдЦрд╛рд▓реА рд╕реНрдЯреНрд░рд┐рдВрдЧ рдХреА рдкрд╣рдЪрд╛рди рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдирд╣реАрдВ рд╣реИред

https://mail.openjdk.java.net/pipermail/core-libs-dev/2020-February/064957.html


!


, :


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

рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ "class '" + getClassName() + "'"рд╕рдорд╛рди рд╣реЛрдЧреА рдФрд░ рд╣рдо рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдбрдмрд▓ рд▓реВрдк рдореЗрдВ рдПрдХ рд╣реА рд▓рд╛рдЗрди рдирд╣реАрдВ рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддреЗ рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рд▓реВрдк рдХреЗ рдмрд╛рд╣рд░ рдЗрд╕реЗ 1 рдмрд╛рд░ рдмрдирд╛рдирд╛ рдмреЗрд╣рддрд░ рд╣реИред рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ, рдЗрд╕ рддрд░рд╣ рдХреЗ рдЙрджрд╛рд╣рд░рдгреЛрдВ рдХреЛ рдкрдХрдбрд╝рдирд╛ рдПрдХ рдореМрдХреЗ рдХреА рдмрд╛рдд рдереА: рдореИрдВрдиреЗ рдкрд╛рдпрд╛ рдХрд┐ рдореЗрд░реЗ рдЖрд╡реЗрджрди рдХреЛ рдбреАрдмрдЧ рдХрд░рддреЗ рд╣реБрдП рд╕реНрд░реЛрдд рдХреЗ рдЕрдВрджрд░ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рд╡рд┐рдлрд▓ рд░рд╣рд╛ рд╣реИред рдЕрдм IDEA-230889 рдХреЗ рд▓рд┐рдП рдзрдиреНрдпрд╡рд╛рдж рдпрд╣ рд╕реНрд╡рдЪрд╛рд▓рд┐рдд рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рдмреЗрд╢рдХ, рдпрд╣ рд╣рдореЗрд╢рд╛ рдПрдХ рдкрд╛рд╢ рдореЗрдВ рдПрдХ рдирдИ рд░реЗрдЦрд╛ рдХреЗ рдирд┐рд░реНрдорд╛рдг рд╕реЗ рджреВрд░ рд╣реИ, рдЪрд╛рд╣реЗ рдорд╛рд░реНрдЧ рдХреА рдкрд░рд╡рд╛рд╣ рдХрд┐рдП рдмрд┐рдирд╛, рд▓реЗрдХрд┐рди рдЗрди рдорд╛рдорд▓реЛрдВ рдореЗрдВ рднреА, рд╣рдо рдЙрди рд▓реЛрдЧреЛрдВ рдХреЛ рдЕрд▓рдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдЬрд┐рдирдореЗрдВ рдХреБрдЫ рд╕реНрдерд╛рдпреА рд╕реНрдерд╛рдпреА рднрд╛рдЧ рд╣реИрдВ:


// org.springframework.beans.factory.support.BeanDefinitionReaderUtils

public static String uniqueBeanName(String beanName, BeanDefinitionRegistry registry) {
  String id = beanName;
  int counter = -1;

  // Increase counter until the id is unique.
  while (counter == -1 || registry.containsBeanDefinition(id)) {
    counter++;
    id = beanName + GENERATED_BEAN_NAME_SEPARATOR + counter;
  }
  return id;
}

рдпрд╣рд╛рдВ рдЙрдкрд╕рд░реНрдЧ beanName + GENERATED_BEAN_NAME_SEPARATORрд╣рдореЗрд╢рд╛ рд╕рдорд╛рди рд╣реЛрддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рдмрд╛рд╣рд░ рд▓рд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред


рдпрд╣ рд╕рдм, рдЯрд┐рдкреНрдкрдгрд┐рдпреЛрдВ рдореЗрдВ рдЕрдкрдиреЗ рдЙрджрд╛рд╣рд░рдг рд▓рд┐рдЦреЗрдВ - рд╣рдо рдЗрд╕реЗ рдХрд╡рд░ рдХрд░реЗрдВрдЧреЗред


All Articles