Удалите все вхождения символа из строки

Этот начал меня в истинный OOA& D.

Применение UML и Шаблонов: Введение в Объектно-ориентированный Анализ и проектирование и Итерационную разработку - Craig Larman

Они произошли бы там также:

  • Шаблоны в Архитектуре приложений для предприятия - Fowler
  • Управляемый Доменом Дизайн - Eric Evans
298
задан Mridang Agarwalla 11 April 2016 в 02:46
поделиться

1 ответ

Оценка основных ответов со сравнительным тестом производительности, который подтверждает опасения, что текущий выбранный ответ делает дорогостоящие regex операции под капотом

До настоящего времени, предоставленные ответы появляются в 3 основных стиля (игнорирующий ответ JavaScript ;)):

  • Использование String.replace (charsToDelete, ""); который использует regex под капотом
  • Лямбда Использования
  • Использование простая реализация Java

С точки зрения размера кода ясно, String.replace является самым кратким. Простая реализация Java является немного меньшей и более чистой (по моему скромному мнению), чем Лямбда (не понимайте меня превратно - я часто использую Лямбды, где они являются соответствующими)

, скорость Выполнения была, в порядке самого быстрого к самому медленному: простая реализация Java, Лямбда и затем String.replace () (который вызывает regex).

Безусловно самая быстрая реализация была простой реализацией Java, настроенной так, чтобы она предварительно выделила буфер StringBuilder макс. возможной длине результата и затем просто добавила символы к буферу, которые не находятся в "символах для удаления" строки. Это избегает, чтобы любой перераспределил, который произошел бы для Строк> 16 символов в длине (выделение по умолчанию для StringBuilder), и это избегает "слайда, оставленного" хит производительности удаления символов из копии строки, которая происходит, реализация Лямбды.

код ниже выполняет простое эталонное тестирование, выполняя каждую реализацию 1,000,000 раз и регистрирует прошедшее время.

точные результаты меняются в зависимости от каждого выполнения, но порядок производительности никогда не изменяется:

Start simple Java implementation
Time: 157 ms
Start Lambda implementation
Time: 253 ms
Start String.replace implementation
Time: 634 ms

реализация Лямбды (как скопировано с ответа Kaplan) может быть медленнее, потому что это выполняет "сдвиг, оставленный один" всех символов направо от удаляемого символа. Это, очевидно, ухудшилось бы для более длинных строк с большим количеством символов, требующих удаления. Также могли бы быть немного служебные в самой реализации Лямбды.

реализация String.replace, использует regex и делает regex "компиляция" в каждом вызове. Оптимизация этого должна была бы использовать regex непосредственно и кэшировать скомпилированный шаблон для предотвращения стоимости компиляции его каждый раз.

package com.sample;

import java.util.function.BiFunction;
import java.util.stream.IntStream;

public class Main {

    static public String deleteCharsSimple(String fromString, String charsToDelete)
    {
        StringBuilder buf = new StringBuilder(fromString.length()); // Preallocate to max possible result length
        for(int i = 0; i < fromString.length(); i++)
            if (charsToDelete.indexOf(fromString.charAt(i)) < 0)
                buf.append(fromString.charAt(i));   // char not in chars to delete so add it
        return buf.toString();
    }

    static public String deleteCharsLambda(String fromString1, String charsToDelete)
    {
        BiFunction<String, String, String> deleteChars = (fromString, chars) -> {
            StringBuilder buf = new StringBuilder(fromString);
            IntStream.range(0, buf.length()).forEach(i -> {
                while (i < buf.length() && chars.indexOf(buf.charAt(i)) >= 0)
                    buf.deleteCharAt(i);
            });
            return (buf.toString());
        };

        return deleteChars.apply(fromString1, charsToDelete);
    }

    static public String deleteCharsReplace(String fromString, String charsToDelete)
    {
        return fromString.replace(charsToDelete, "");
    }


    public static void main(String[] args)
    {
        String str = "XXXTextX XXto modifyX";
        String charsToDelete = "X";  // Should only be one char as per OP's requirement

        long start, end;

        System.out.println("Start simple");
        start = System.currentTimeMillis();

        for (int i = 0; i < 1000000; i++)
            deleteCharsSimple(str, charsToDelete);

        end = System.currentTimeMillis();
        System.out.println("Time: " + (end - start));

        System.out.println("Start lambda");
        start = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++)
            deleteCharsLambda(str, charsToDelete);

        end = System.currentTimeMillis();
        System.out.println("Time: " + (end - start));

        System.out.println("Start replace");
        start = System.currentTimeMillis();

        for (int i = 0; i < 1000000; i++)
            deleteCharsReplace(str, charsToDelete);

        end = System.currentTimeMillis();
        System.out.println("Time: " + (end - start));
    }
}
0
ответ дан 23 November 2019 в 01:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: