Ответ 1
Я думаю, что это должно быть с substring до JDK 7.
В то время размер массива базового символа не обязательно был размером строки. Было два поля: offset
и count
(i
an j
соответственно), которые показывали, где строка this
в базовом массиве, поэтому метод был:
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = count;
if (n == anotherString.count) {
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;
while (n-- != 0) {
if (v1[i++] != v2[j++])
return false;
}
return true;
}
}
return false;
}
После изменения, упомянутого выше, этот метод также должен был быть изменен, поэтому они просто фиксировали n, чтобы теперь быть длиной массива:
int n = value.length;
и избавился от j
(потому что больше нет смещения):
int i = 0;
Теперь, поскольку i
должен быть увеличен после двух обычаев, он увеличивается в отдельном выражении:
if (v1[i] != v2[i])
return false;
i++;
Я думаю, что это более сжатая реализация, которая очевидна, если писать ее с нуля, но учитывая, что это было изменение, вызванное другим изменением... Oracle люди простые люди, как и мы:)
Бенчмаркинг
Что касается бенчмаркинга String#equals
vs Arrays#equals(char[], char[]
), я думаю, что мы должны сравнивать яблоки с яблоками, поэтому я поставил два подхода для сравнения 2 массивов символов:
public static void main(String[] args) {
final Random random = new Random();
final int arrays = 10000;
final int chars = 1000;
// generate the arrays
char[][] array = new char[arrays][chars];
for (int i = 0; i < arrays; i++) {
for (int j = 0; j < chars; j++) {
array[i][j] = (char)(random.nextInt(94) + 33);
}
}
// compare using Arrays equals
long before = System.nanoTime();
for (int i = 0; i < arrays; i++) {
for (int j = 0; j < chars; j++) {
equals_Arrays(array[i], array[j]);
}
}
System.out.println(System.nanoTime() - before);
// compare using String equals
before = System.nanoTime();
for (int i = 0; i < arrays; i++) {
for (int j = 0; j < chars; j++) {
equals_String(array[i], array[j]);
}
}
System.out.println(System.nanoTime() - before);
}
private static boolean equals_Arrays(char[] a, char[] a2) {
if (a == a2)
return true;
if (a == null || a2 == null)
return false;
int length = a.length;
if (a2.length != length)
return false;
for (int i = 0; i < length; i++)
if (a[i] != a2[i])
return false;
return true;
}
private static boolean equals_String(char[] v1, char[] v2) {
if (v1 == v2)
return true;
if (v1 == null || v2 == null)
return false;
int length = v1.length;
if (length == v2.length) {
int i = 0;
while (length-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
return false;
}
В моей коробке я не вижу заметной разницы.