Проблемы — boxing Character, временные списки, квадратичная конкатенация в toString и линейный поиск уже встреченных символов. Для обычной строки проще делегировать хранение StringBuilder.
Анализ кода: реализация MyStringBuilder
Проблемы — 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. Потокобезопасность этим решением не добавляется.