Отсортировать информацию по правилу

Отсортировать информацию по правилу: теме теста один раз, далее фамилия тестируемого и результат тестирования.
Ввод производится в список
В формате Фамилия тема_теста/оценка
Пример:
Ввод:
Иванов массивы/5.00,списки/3.49
Сидоров массивы/4.50,классы/5.00
Вывод:
массивы
Иванов 5.00
Сидоров 4.50
списки
Иванов 3.49
классы
Сидоров 5.00
Суть вопроса: Как это можно реализовать что бы тема теста не повторялась Код который я набросал
Необходимо реализовать все без классов без MAP. Только списком необязательно одним но ввод должен производится в один список после чего только разбивать на несколько списков

Scanner in= new Scanner(System.in);
    List result = new ArrayList();
    List nameOfTests = new ArrayList();
    System.out.println("Начните вводить Фамилию + тему теста +оценку)(В формате Фамилия тема_теста/оценка). Окончанием служит 0 ");
    String str = in.nextLine();
    while(!(str.equals("0"))) {
        result.add(str);
        str = in.nextLine();
    }
    
    
    for (int i = 0;i<result.size();i++){
                str = (String) result.get(i);
                String[] str1 = str.split(" ");
                String[] str2 = str1[1].split(",");
                for(int j = 0;j<str2.length;j++){
                    String[] str3 = str2[j].split("/");
                    nameOfTests.add(str3[0]);
                    
                }
            }
            Set<String> set = new HashSet<>(nameOfTests);
            nameOfTests.clear();
            nameOfTests.addAll(set);
            for(int i = 0;i<result.size();i++){
                str = (String) result.get(i);
                String[] str1 = str.split(" ");
                String[] str2 = str1[1].split(",");
                String newstr = (String) nameOfTests.get(i);
                System.out.println(newstr);
                for(int j = 0;j<str2.length;j++){
                    String[] str3 = str2[j].split("/");
                    str = (String) result.get(i);
                    String[] str4 = str.split(" ");
                    String[] str5 = str4[1].split(",");
                    for (int raw = 0;raw<str5.length;raw++){
                        String[] str6 = str5[raw].split("/");
                        if(newstr.equals(str6[0])){
                            System.out.println(str4[0]);
                            System.out.println(str6[1]);
                        }
                        
                    }
            }
            }

Получается вот так вот


Ответы (2 шт):

Автор решения: siarhei987

Вариант решения с использованием массивов и списков.

import java.util.*;

public class SO1417577 {

    public static void main(String[] args) {

        Scanner in = new Scanner(System.in);
        List<String> allStudentsResults = new ArrayList<>();

        String input = in.nextLine();
        while (!input.equals("0")) {
            allStudentsResults.add(input);
            input = in.nextLine();
        }

        List<String> testNames = getAllTestNames(allStudentsResults);

        for (String testName : testNames) {
            System.out.println(testName);
            for (String studentResults : allStudentsResults) {
                printStudentResult(studentResults, testName);
            }
        }
    }

    /**
     * Извлекает название тестов из строки содержащей информацию о результатах студента.
     *
     * @param studentResults строка вида Иванов массивы/5.00,списки/3.55
     * @return массив названий тестов для одного студента
     */
    private static List<String> getTestNames(String studentResults) {

        List<String> names = new ArrayList<>();

        String tests = studentResults.split(" ")[1];
        for (String test : tests.split(",")) {
            String testName = test.split("/")[0];
            names.add(testName);
        }

        return names;

    }

    /**
     * Ивлекает из inputData названия тестов.
     *
     * @param inputData список из строк вида Иванов массивы/5.00,списки/3.55
     * @return список названий тестов без дубликатов
     */
    private static List<String> getAllTestNames(List<String> inputData) {

        List<String> testNames = new ArrayList<>();

        for (String line : inputData) {
            for (String testName : getTestNames(line)) {
                if (!testNames.contains(testName)) {
                    testNames.add(testName);
                }
            }
        }

        return testNames;

    }

    /**
     * Выводит в консоль студента и его результат по тесту testName
     *
     * @param studentResults строка вида Иванов массивы/5.00,списки/3.55
     * @param testName имя теста
     */
    private static void printStudentResult(String studentResults, String testName) {

        if (studentResults.contains(testName)) {

            final int symbolsInGrade = 4;
            int startIndexForTestGrade = studentResults.indexOf(testName) + testName.length() + 1;
            int endIndexForTestGrade = startIndexForTestGrade + symbolsInGrade;

            String studentName = studentResults.substring(0, studentResults.indexOf(" "));
            String grade = studentResults.substring(startIndexForTestGrade, endIndexForTestGrade);

            System.out.println(studentName + " " + grade);

        }

    }

}

Для ввода:

Аня массивы/5.00,списки/3.55
Дима классы/5.00,списки/3.55
Света алгоритмы/5.00,списки/3.55
Катя алгоритмы/4.70
0

Вывод будет:

массивы
Аня 5.00
списки
Аня 3.55
Дима 3.55
Света 3.55
классы
Дима 5.00
алгоритмы
Света 5.00
Катя 4.70
→ Ссылка
Автор решения: Tufuteca

Посидев подумав один вечер пришёл к ответу который меня устроил. Вот код

Scanner in= new Scanner(System.in);
    List result = new ArrayList();
    List nameOfTests = new ArrayList();
    System.out.println("Начните вводить Фамилию + тему теста/оценка (темы через запятую). Окончанием служит 0 ");
    String str = in.nextLine();
    while(!(str.equals("0"))) {
        result.add(str);
        str = in.nextLine();
    }
    for (int i = 0;i<result.size();i++){
                str = (String) result.get(i);
                String[] str1 = str.split(" ");
                String[] str2 = str1[1].split(",");
                for(int j = 0;j<str2.length;j++){
                    String[] str3 = str2[j].split("/");
                    nameOfTests.add(str3[0]);
                    
                }
            }
            Set<String> set = new HashSet<>(nameOfTests);
            nameOfTests.clear();
            nameOfTests.addAll(set);
            Collections.sort(result);
            for (int j = 0;j<nameOfTests.size();j++){
                System.out.println();
                    String str1 = (String) nameOfTests.get(j);
                    System.out.println(nameOfTests.get(j));
            for(int i = 0 ;i<result.size();i++){
                str = (String) result.get(i);
                if(str.contains(str1)){
                    String[] str2 = str.split(" ");
                    String[] str3 = str2[1].split(",");
                    for(int raw=0;raw<str3.length;raw++){
                        String[] str4 = str3[raw].split("/");
                        if(str4[0].equals(str1)){
                            System.out.println(str2[0]+" "+str4[1]);
                    }
                }
            }
}

}

→ Ссылка