< prev index next >

src/java.base/share/classes/java/lang/String.java

Print this page

        

*** 73,83 **** * Here are some more examples of how strings can be used: * <blockquote><pre> * System.out.println("abc"); * String cde = "cde"; * System.out.println("abc" + cde); ! * String c = "abc".substring(2, 3); * String d = cde.substring(1, 2); * </pre></blockquote> * <p> * The class {@code String} includes methods for examining * individual characters of the sequence, for comparing strings, for --- 73,83 ---- * Here are some more examples of how strings can be used: * <blockquote><pre> * System.out.println("abc"); * String cde = "cde"; * System.out.println("abc" + cde); ! * String c = "abc".substring(2,3); * String d = cde.substring(1, 2); * </pre></blockquote> * <p> * The class {@code String} includes methods for examining * individual characters of the sequence, for comparing strings, for
*** 162,177 **** private final byte coder; /** Cache the hash code for the string */ private int hash; // Default to 0 - /** - * Cache if the hash has been calculated as actually being zero, enabling - * us to avoid recalculating this. - */ - private boolean hashIsZero; // Default to false; - /** use serialVersionUID from JDK 1.0.2 for interoperability */ private static final long serialVersionUID = -6849794470754667710L; /** * If String compaction is disabled, the bytes in {@code value} are --- 162,171 ----
*** 1018,1029 **** if (this == anObject) { return true; } if (anObject instanceof String) { String aString = (String)anObject; ! if (!COMPACT_STRINGS || this.coder == aString.coder) { ! return StringLatin1.equals(value, aString.value); } } return false; } --- 1012,1024 ---- if (this == anObject) { return true; } if (anObject instanceof String) { String aString = (String)anObject; ! if (coder() == aString.coder()) { ! return isLatin1() ? StringLatin1.equals(value, aString.value) ! : StringUTF16.equals(value, aString.value); } } return false; }
*** 1054,1073 **** if (len != sb.length()) { return false; } byte v1[] = value; byte v2[] = sb.getValue(); ! byte coder = coder(); ! if (coder == sb.getCoder()) { int n = v1.length; for (int i = 0; i < n; i++) { if (v1[i] != v2[i]) { return false; } } } else { ! if (coder != LATIN1) { // utf16 str and latin1 abs can never be "equal" return false; } return StringUTF16.contentEquals(v1, v2, len); } return true; --- 1049,1067 ---- if (len != sb.length()) { return false; } byte v1[] = value; byte v2[] = sb.getValue(); ! if (coder() == sb.getCoder()) { int n = v1.length; for (int i = 0; i < n; i++) { if (v1[i] != v2[i]) { return false; } } } else { ! if (!isLatin1()) { // utf16 str and latin1 abs can never be "equal" return false; } return StringUTF16.contentEquals(v1, v2, len); } return true;
*** 1207,1223 **** * lexicographically greater than the string argument. */ public int compareTo(String anotherString) { byte v1[] = value; byte v2[] = anotherString.value; ! byte coder = coder(); ! if (coder == anotherString.coder()) { ! return coder == LATIN1 ? StringLatin1.compareTo(v1, v2) ! : StringUTF16.compareTo(v1, v2); } ! return coder == LATIN1 ? StringLatin1.compareToUTF16(v1, v2) ! : StringUTF16.compareToLatin1(v1, v2); } /** * A Comparator that orders {@code String} objects as by * {@code compareToIgnoreCase}. This comparator is serializable. --- 1201,1216 ---- * lexicographically greater than the string argument. */ public int compareTo(String anotherString) { byte v1[] = value; byte v2[] = anotherString.value; ! if (coder() == anotherString.coder()) { ! return isLatin1() ? StringLatin1.compareTo(v1, v2) ! : StringUTF16.compareTo(v1, v2); } ! return isLatin1() ? StringLatin1.compareToUTF16(v1, v2) ! : StringUTF16.compareToLatin1(v1, v2); } /** * A Comparator that orders {@code String} objects as by * {@code compareToIgnoreCase}. This comparator is serializable.
*** 1237,1253 **** private static final long serialVersionUID = 8575799808933029326L; public int compare(String s1, String s2) { byte v1[] = s1.value; byte v2[] = s2.value; ! byte coder = s1.coder(); ! if (coder == s2.coder()) { ! return coder == LATIN1 ? StringLatin1.compareToCI(v1, v2) ! : StringUTF16.compareToCI(v1, v2); } ! return coder == LATIN1 ? StringLatin1.compareToCI_UTF16(v1, v2) ! : StringUTF16.compareToCI_Latin1(v1, v2); } /** Replaces the de-serialized object. */ private Object readResolve() { return CASE_INSENSITIVE_ORDER; } } --- 1230,1245 ---- private static final long serialVersionUID = 8575799808933029326L; public int compare(String s1, String s2) { byte v1[] = s1.value; byte v2[] = s2.value; ! if (s1.coder() == s2.coder()) { ! return s1.isLatin1() ? StringLatin1.compareToCI(v1, v2) ! : StringUTF16.compareToCI(v1, v2); } ! return s1.isLatin1() ? StringLatin1.compareToCI_UTF16(v1, v2) ! : StringUTF16.compareToCI_Latin1(v1, v2); } /** Replaces the de-serialized object. */ private Object readResolve() { return CASE_INSENSITIVE_ORDER; } }
*** 1317,1328 **** if ((ooffset < 0) || (toffset < 0) || (toffset > (long)length() - len) || (ooffset > (long)other.length() - len)) { return false; } ! byte coder = coder(); ! if (coder == other.coder()) { if (!isLatin1() && (len > 0)) { toffset = toffset << 1; ooffset = ooffset << 1; len = len << 1; } --- 1309,1319 ---- if ((ooffset < 0) || (toffset < 0) || (toffset > (long)length() - len) || (ooffset > (long)other.length() - len)) { return false; } ! if (coder() == other.coder()) { if (!isLatin1() && (len > 0)) { toffset = toffset << 1; ooffset = ooffset << 1; len = len << 1; }
*** 1330,1340 **** if (tv[toffset++] != ov[ooffset++]) { return false; } } } else { ! if (coder == LATIN1) { while (len-- > 0) { if (StringLatin1.getChar(tv, toffset++) != StringUTF16.getChar(ov, ooffset++)) { return false; } --- 1321,1331 ---- if (tv[toffset++] != ov[ooffset++]) { return false; } } } else { ! if (coder() == LATIN1) { while (len-- > 0) { if (StringLatin1.getChar(tv, toffset++) != StringUTF16.getChar(ov, ooffset++)) { return false; }
*** 1412,1428 **** || (ooffset > (long)other.length() - len)) { return false; } byte tv[] = value; byte ov[] = other.value; ! byte coder = coder(); ! if (coder == other.coder()) { ! return coder == LATIN1 ? StringLatin1.regionMatchesCI(tv, toffset, ov, ooffset, len) : StringUTF16.regionMatchesCI(tv, toffset, ov, ooffset, len); } ! return coder == LATIN1 ? StringLatin1.regionMatchesCI_UTF16(tv, toffset, ov, ooffset, len) : StringUTF16.regionMatchesCI_Latin1(tv, toffset, ov, ooffset, len); } /** --- 1403,1418 ---- || (ooffset > (long)other.length() - len)) { return false; } byte tv[] = value; byte ov[] = other.value; ! if (coder() == other.coder()) { ! return isLatin1() ? StringLatin1.regionMatchesCI(tv, toffset, ov, ooffset, len) : StringUTF16.regionMatchesCI(tv, toffset, ov, ooffset, len); } ! return isLatin1() ? StringLatin1.regionMatchesCI_UTF16(tv, toffset, ov, ooffset, len) : StringUTF16.regionMatchesCI_Latin1(tv, toffset, ov, ooffset, len); } /**
*** 1449,1468 **** } byte ta[] = value; byte pa[] = prefix.value; int po = 0; int pc = pa.length; ! byte coder = coder(); ! if (coder == prefix.coder()) { ! int to = (coder == LATIN1) ? toffset : toffset << 1; while (po < pc) { if (ta[to++] != pa[po++]) { return false; } } } else { ! if (coder == LATIN1) { // && pcoder == UTF16 return false; } // coder == UTF16 && pcoder == LATIN1) while (po < pc) { if (StringUTF16.getChar(ta, toffset++) != (pa[po++] & 0xff)) { --- 1439,1457 ---- } byte ta[] = value; byte pa[] = prefix.value; int po = 0; int pc = pa.length; ! if (coder() == prefix.coder()) { ! int to = isLatin1() ? toffset : toffset << 1; while (po < pc) { if (ta[to++] != pa[po++]) { return false; } } } else { ! if (isLatin1()) { // && pcoder == UTF16 return false; } // coder == UTF16 && pcoder == LATIN1) while (po < pc) { if (StringUTF16.getChar(ta, toffset++) != (pa[po++] & 0xff)) {
*** 1517,1541 **** * (The hash value of the empty string is zero.) * * @return a hash code value for this object. */ public int hashCode() { - // The hash or hashIsZero fields are subject to a benign data race, - // making it crucial to ensure that any observable result of the - // calculation in this method stays correct under any possible read of - // these fields. Necessary restrictions to allow this to be correct - // without explicit memory fences or similar concurrency primitives is - // that we can ever only write to one of these two fields for a given - // String instance, and that the computation is idempotent and derived - // from immutable state int h = hash; ! if (h == 0 && !hashIsZero) { h = isLatin1() ? StringLatin1.hashCode(value) : StringUTF16.hashCode(value); ! if (h == 0) { ! hashIsZero = true; ! } else { hash = h; } } return h; } --- 1506,1523 ---- * (The hash value of the empty string is zero.) * * @return a hash code value for this object. */ public int hashCode() { int h = hash; ! if (h == 0 && value.length > 0) { h = isLatin1() ? StringLatin1.hashCode(value) : StringUTF16.hashCode(value); ! // Avoid issuing a store if the calculated value is also zero: ! // in addition to a minor performance benefit, this allows storing ! // Strings with zero hash code in read-only memory. ! if (h != 0) { hash = h; } } return h; }
*** 1691,1706 **** * @param str the substring to search for. * @return the index of the first occurrence of the specified substring, * or {@code -1} if there is no such occurrence. */ public int indexOf(String str) { ! byte coder = coder(); ! if (coder == str.coder()) { return isLatin1() ? StringLatin1.indexOf(value, str.value) : StringUTF16.indexOf(value, str.value); } ! if (coder == LATIN1) { // str.coder == UTF16 return -1; } return StringUTF16.indexOfLatin1(value, str.value); } --- 1673,1687 ---- * @param str the substring to search for. * @return the index of the first occurrence of the specified substring, * or {@code -1} if there is no such occurrence. */ public int indexOf(String str) { ! if (coder() == str.coder()) { return isLatin1() ? StringLatin1.indexOf(value, str.value) : StringUTF16.indexOf(value, str.value); } ! if (coder() == LATIN1) { // str.coder == UTF16 return -1; } return StringUTF16.indexOfLatin1(value, str.value); }
*** 1969,1979 **** */ public String concat(String str) { if (str.isEmpty()) { return this; } ! return StringConcatHelper.simpleConcat(this, str); } /** * Returns a string resulting from replacing all occurrences of * {@code oldChar} in this string with {@code newChar}. --- 1950,1973 ---- */ public String concat(String str) { if (str.isEmpty()) { return this; } ! if (coder() == str.coder()) { ! byte[] val = this.value; ! byte[] oval = str.value; ! int len = val.length + oval.length; ! byte[] buf = Arrays.copyOf(val, len); ! System.arraycopy(oval, 0, buf, val.length, oval.length); ! return new String(buf, coder); ! } ! int len = length(); ! int olen = str.length(); ! byte[] buf = StringUTF16.newBytesFor(len + olen); ! getBytes(buf, 0, UTF16); ! str.getBytes(buf, len, UTF16); ! return new String(buf, UTF16); } /** * Returns a string resulting from replacing all occurrences of * {@code oldChar} in this string with {@code newChar}.
*** 2158,2209 **** * @param replacement The replacement sequence of char values * @return The resulting string * @since 1.5 */ public String replace(CharSequence target, CharSequence replacement) { ! String trgtStr = target.toString(); String replStr = replacement.toString(); ! int thisLen = length(); ! int trgtLen = trgtStr.length(); ! int replLen = replStr.length(); ! ! if (trgtLen > 0) { ! if (trgtLen == 1 && replLen == 1) { ! return replace(trgtStr.charAt(0), replStr.charAt(0)); ! } ! ! boolean thisIsLatin1 = this.isLatin1(); ! boolean trgtIsLatin1 = trgtStr.isLatin1(); ! boolean replIsLatin1 = replStr.isLatin1(); ! String ret = (thisIsLatin1 && trgtIsLatin1 && replIsLatin1) ! ? StringLatin1.replace(value, thisLen, ! trgtStr.value, trgtLen, ! replStr.value, replLen) ! : StringUTF16.replace(value, thisLen, thisIsLatin1, ! trgtStr.value, trgtLen, trgtIsLatin1, ! replStr.value, replLen, replIsLatin1); ! if (ret != null) { ! return ret; ! } return this; - - } else { // trgtLen == 0 - int resultLen; - try { - resultLen = Math.addExact(thisLen, Math.multiplyExact( - Math.addExact(thisLen, 1), replLen)); - } catch (ArithmeticException ignored) { - throw new OutOfMemoryError(); - } - - StringBuilder sb = new StringBuilder(resultLen); - sb.append(replStr); - for (int i = 0; i < thisLen; ++i) { - sb.append(charAt(i)).append(replStr); - } - return sb.toString(); } } /** * Splits this string around matches of the given * <a href="../util/regex/Pattern.html#sum">regular expression</a>. --- 2152,2182 ---- * @param replacement The replacement sequence of char values * @return The resulting string * @since 1.5 */ public String replace(CharSequence target, CharSequence replacement) { ! String tgtStr = target.toString(); String replStr = replacement.toString(); ! int j = indexOf(tgtStr); ! if (j < 0) { return this; } + int tgtLen = tgtStr.length(); + int tgtLen1 = Math.max(tgtLen, 1); + int thisLen = length(); + + int newLenHint = thisLen - tgtLen + replStr.length(); + if (newLenHint < 0) { + throw new OutOfMemoryError(); + } + StringBuilder sb = new StringBuilder(newLenHint); + int i = 0; + do { + sb.append(this, i, j).append(replStr); + i = j + tgtLen; + } while (j < thisLen && (j = indexOf(tgtStr, j + tgtLen1)) > 0); + return sb.append(this, i, thisLen).toString(); } /** * Splits this string around matches of the given * <a href="../util/regex/Pattern.html#sum">regular expression</a>.
< prev index next >