Из вашего вопроса неясно, что именно должен делать код. Находит ли это первое '.' и заменить все до него на «*»? Или за этим стоит какая-то причудливая логика? Может быть, все до nth '.' заменяется на '*'?
Если вы пытаетесь найти экземпляр конкретной строки, используйте что-то вроде алгоритма Бойера-Мура . Он должен быть в состоянии найти соответствие для вас, и вы можете заменить то, что вы хотите.
Имейте в виду, что String
в Java является неизменным. Может быть быстрее изменить последовательность на месте. Проверьте другие реализации CharSequence
, чтобы увидеть, что вы можете сделать, например, StringBuffer и CharBuffer . Если параллелизм не требуется, StringBuilder может быть вариантом.
Используя изменяемый CharSequence
вместо методов на String
, вы избегаете оттока объектов. Если все, что вы делаете, это замените некоторый фрагмент базового символьного массива более коротким массивом (то есть {'*'}
), это, вероятно, приведет к ускорению, поскольку такие копии массива довольно оптимизированы . Вы все еще будете делать копию массива в конце дня, но это может быть быстрее, чем новые String
выделения.
UPDATE
Все вышесказанное - в значительной степени фигня. Конечно, может быть, вы можете реализовать свой собственный CharSequence
, который дает вам лучшую нарезку и лениво изменяет размер массива (иначе фактически ничего не обрезает, пока это абсолютно не нужно), возвращая Strings
на основе смещений и еще много чего. Но StringBuffer
и StringBuilder
, по крайней мере напрямую, не работают так же хорошо, как опубликованное решение. CharBuffer
полностью неприменимо; Я не осознавал, что это был урок nio раньше: он предназначен для других вещей.
В коде поли есть несколько интересных моментов, которые меня интересуют, знал ли он или она до публикации, а именно, что изменение "*"
в последних строках методов на '*'
приводит к значительному замедлению.
Тем не менее, вот мой тест. Я обнаружил одну небольшую оптимизацию: объявление выражений '.'
и "*"
в качестве констант добавляет немного ускорения, а также использование StringBuilder
в локальной области вместо оператора конкатенации двоичных инфиксных строк.
Я знаю, что gc()
в лучшем случае является рекомендацией, а в худшем - неактивным, но я подумал, что добавление его с небольшим временем ожидания может позволить ВМ выполнить некоторую очистку после создания 1M String
s. Кто-то может исправить меня, если это совершенно наивно.
Простой бенчмарк
import java.util.ArrayList;
import java.util.Arrays;
public class StringSplitters {
private static final String PREFIX = "*";
private static final char DOT = '.';
public static String starOutFirst(String s) {
final int k = s.indexOf(DOT);
return PREFIX + s.substring(k);
}
public static String starOutFirstSb(String s) {
StringBuilder sb = new StringBuilder();
final int k = s.indexOf(DOT);
return sb.append(PREFIX).append(s.substring(k)).toString();
}
public static void main(String[] args) throws InterruptedException {
double[] firstRates = new double[10];
double[] firstSbRates = new double[10];
double firstAvg = 0;
double firstSbAvg = 0;
double firstMin = Double.POSITIVE_INFINITY;
double firstMax = Double.NEGATIVE_INFINITY;
double firstSbMin = Double.POSITIVE_INFINITY;
double firstSbMax = Double.NEGATIVE_INFINITY;
for (int i = 0; i < 10; i++) {
firstRates[i] = testFirst();
firstAvg += firstRates[i];
if (firstRates[i] < firstMin)
firstMin = firstRates[i];
if (firstRates[i] > firstMax)
firstMax = firstRates[i];
Thread.sleep(100);
System.gc();
Thread.sleep(100);
}
firstAvg /= 10.0d;
for (int i = 0; i < 10; i++) {
firstSbRates[i] = testFirstSb();
firstSbAvg += firstSbRates[i];
if (firstSbRates[i] < firstSbMin)
firstSbMin = firstSbRates[i];
if (firstSbRates[i] > firstSbMax)
firstSbMax = firstSbRates[i];
Thread.sleep(100);
System.gc();
Thread.sleep(100);
}
firstSbAvg /= 10.0d;
System.out.printf("First:\n\tMin:\t%07.3f\tMax:\t%07.3f\tAvg:\t%07.3f\n\tRates:\t%s\n\n", firstMin, firstMax,
firstAvg, Arrays.toString(firstRates));
System.out.printf("FirstSb:\n\tMin:\t%07.3f\tMax:\t%07.3f\tAvg:\t%07.3f\n\tRates:\t%s\n\n", firstSbMin,
firstSbMax, firstSbAvg, Arrays.toString(firstSbRates));
}
private static double testFirst() {
ArrayList<String> strings = new ArrayList<String>(1000000);
for (int i = 0; i < 1000000; i++) {
int first = (int) (Math.random() * 128);
int second = (int) (Math.random() * 128);
int third = (int) (Math.random() * 128);
int fourth = (int) (Math.random() * 128);
strings.add(String.format("%d.%d.%d.%d", first, second, third, fourth));
}
long before = System.currentTimeMillis();
for (String s : strings) {
starOutFirst(s);
}
long after = System.currentTimeMillis();
return 1000000000.0d / (after - before);
}
private static double testFirstSb() {
ArrayList<String> strings = new ArrayList<String>(1000000);
for (int i = 0; i < 1000000; i++) {
int first = (int) (Math.random() * 128);
int second = (int) (Math.random() * 128);
int third = (int) (Math.random() * 128);
int fourth = (int) (Math.random() * 128);
strings.add(String.format("%d.%d.%d.%d", first, second, third, fourth));
}
long before = System.currentTimeMillis();
for (String s : strings) {
starOutFirstSb(s);
}
long after = System.currentTimeMillis();
return 1000000000.0d / (after - before);
}
}
выход
First:
Min: 3802281.369 Max: 5434782.609 Avg: 5185796.131
Rates: [3802281.3688212926, 5181347.150259067, 5291005.291005291, 5376344.086021505, 5291005.291005291, 5235602.094240838, 5434782.608695652, 5405405.405405405, 5434782.608695652, 5405405.405405405]
FirstSb:
Min: 4587155.963 Max: 5747126.437 Avg: 5462087.511
Rates: [4587155.963302752, 5747126.436781609, 5617977.528089887, 5208333.333333333, 5681818.181818182, 5586592.17877095, 5586592.17877095, 5524861.878453039, 5524861.878453039, 5555555.555555556]