Анализ кода: реализация MyStringBuilder

Проблемы — boxing Character, временные списки, квадратичная конкатенация в toString и линейный поиск уже встреченных символов. Для обычной строки проще делегировать хранение StringBuilder.

Короткий ответ

Что ответить на собеседовании

Проблемы — boxing Character, временные списки, квадратичная конкатенация в toString и линейный поиск уже встреченных символов. Для обычной строки проще делегировать хранение StringBuilder.

Подробный разбор

Ответ с пояснениями

Условие

Класс MyStringBuilder предоставляет базовый набор операций: добавление строки в конец, добавление строки в начало, получение символа по индексу, преобразование в обычный String и подсчёт количества разных символов. Необходимо обнаружить проблемные места, анти‑паттерны и неэффективные участки реализации, а также предложить пути их улучшения.

public class MyStringBuilder {
    private final List<Character> chars;

    public MyStringBuilder() {
        chars = new ArrayList<>();
    }

    public void addToEnd(String s) {
        List<Character> list = new ArrayList<>();
        for (char c : s.toCharArray()) {
            list.add(c);
        }
        chars.addAll(list);
    }

    public void addToStart(String s) {
        List<Character> list = new ArrayList<>();
        for (char c : s.toCharArray()) {
            list.add(c);
        }
        chars.addAll(0, list);
    }

    public Character get(int index) {
        return chars.get(index);
    }

    @Override
    public String toString() {
        var result = "";
        for (var nextChar : chars) {
            result += nextChar;
        }
        return result;
    }

    public int distinctCharsCount() {
        var differentCharacters = new ArrayList<Character>();
        for (var c : chars) {
            if (differentCharacters.indexOf(c) == -1)
                differentCharacters.add(c);
        }
        return differentCharacters.size();
    }
}
public class Main {
    public static void main(String[] args) {
        var builder = new MyStringBuilder();
        builder.addToEnd("aa");
        System.out.println(builder.distinctCharsCount()); // 1
        builder.addToStart("bb");
        builder.addToStart("ab");
        System.out.println(builder.distinctCharsCount()); // 2
        System.out.println(builder); // abbbaa
    }
}

Ответ

Проблемы — boxing Character, временные списки, квадратичная конкатенация в toString и линейный поиск уже встреченных символов. Для обычной строки проще делегировать хранение StringBuilder.

Вариант с теми же UTF-16 char-семантиками:

public class MyStringBuilder {
    private final StringBuilder value = new StringBuilder();
    public void addToEnd(String s) { value.append(java.util.Objects.requireNonNull(s)); }
    public void addToStart(String s) { value.insert(0, java.util.Objects.requireNonNull(s)); }
    public Character get(int index) { return value.charAt(index); }
    @Override public String toString() { return value.toString(); }
    public int distinctCharsCount() {
        return (int) value.chars().distinct().count();
    }
}

Вставка в начало всё ещё O(n), а для Unicode code points нужен codePoints(), что изменит смысл подсчёта. Пример печатает 1, 2 и abbbaa. Потокобезопасность этим решением не добавляется.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее