Task Livecoding Java Code Review Fixes

23. Код-ревью и исправление ошибок #

Условие задачи:
🔍 Провести код-ревью класса Test, исправить ошибки и предложить улучшения.

Код

public class Test {
    private List<String> list = new LinkedList<String>();

    public synchronized void addString(String s) {
        list.add(s);
    }

    public void addStringsFromFile(String pathToFile) throws IOException {
        File file = new File(pathToFile);
        FileInputStream fis = new FileInputStream(file);
        InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.UTF_8);
        Scanner scanner = new Scanner(isr);
        String str;
        while (scanner.hasNextLine()) {
            str = scanner.nextLine();
            if (!str.isBlank()) {
                addString(str);
            }
        }
    }

    public void removeString(int i) {
        list.remove(i);
    }

    public List<String> getList() {
        return list;
    }

    public synchronized String formatString() {
        String s = """";
        for (int i = 0; i < list.size(); i++) {
            s = s + list.get(i);
        }
        return s;
    }
}
Спойлеры к решению
Решение

Замеченные проблемы:
Не хватает потокобезопасности. synchronized используется в addString() и formatString(), но removeString() и getList() не защищены.
Не закрывается Scanner. Это может привести к утечке ресурсов.
FileInputStream можно заменить на Files.newBufferedReader(). Удобнее и безопаснее.
Строки конкатенируются через + в formatString(). Это неэффективно, лучше StringBuilder.
Используется LinkedList<String>. Для частого чтения больше подходит ArrayList.


Исправленный код:

import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Scanner;

public class Test {
    private final List<String> list = Collections.synchronizedList(new ArrayList<>());

    public void addString(String s) {
        list.add(s);
    }

    public void addStringsFromFile(String pathToFile) throws IOException {
        try (BufferedReader reader = Files.newBufferedReader(Path.of(pathToFile), StandardCharsets.UTF_8)) {
            String line;
            while ((line = reader.readLine()) != null) {
                if (!line.isBlank()) {
                    addString(line);
                }
            }
        }
    }

    public void removeString(int i) {
        if (i >= 0 && i < list.size()) {
            list.remove(i);
        }
    }

    public List<String> getList() {
        return Collections.unmodifiableList(list);
    }

    public String formatString() {
        synchronized (list) {
            StringBuilder sb = new StringBuilder();
            for (String s : list) {
                sb.append(s);
            }
            return sb.toString();
        }
    }
}

Исправления и улучшения:
list теперь потокобезопасен (Collections.synchronizedList).
Scanner заменён на BufferedReader + Files.newBufferedReader().
formatString() теперь использует StringBuilder (быстрее, чем s + list.get(i)).
removeString() теперь проверяет границы индекса.
getList() теперь возвращает неизменяемый список (unmodifiableList()).

🚀 Теперь код быстрее, безопаснее и читабельнее! 🔥