From 37f02bf3a062bac57d155670d677ba2572509b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BE=D0=BB=D0=BE=D0=B4=D0=B8=D0=BD=20=D0=93=D0=B5?= =?UTF-8?q?=D1=80=D0=BC=D0=B0=D0=BD?= Date: Sat, 22 Aug 2026 21:18:44 +0400 Subject: [PATCH 01/28] docs: add guide for dependencies between git branches --- GIT_BRANCH_DEPENDENCIES.ru.md | 122 ++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 GIT_BRANCH_DEPENDENCIES.ru.md diff --git a/GIT_BRANCH_DEPENDENCIES.ru.md b/GIT_BRANCH_DEPENDENCIES.ru.md new file mode 100644 index 0000000..f427e43 --- /dev/null +++ b/GIT_BRANCH_DEPENDENCIES.ru.md @@ -0,0 +1,122 @@ +# Работа с зависимостями между Git-ветками + +## Сценарий + +Предположим, мы находимся в ветке: + +```bash +feature/student +``` + +В этой ветке реализуется функциональность, связанная со `Student`. + +При этом у нас появляется новая, независимая по смыслу фича: + +```bash +feature/sorting +``` + +Для реализации сортировки нам необходим класс или интерфейс `Student`, который уже был создан в `feature/student`. + +## Как создать новую ветку + +Если нам необходимо продолжить разработку `feature/sorting`, используя текущее состояние `feature/student`, создаём новую ветку **от `feature/student`**. + +Сначала переключаемся на `feature/student`: + +```bash +git checkout feature/student +``` + +Затем создаём новую ветку: + +```bash +git branch feature/sorting +``` + +После этого история будет выглядеть примерно так: + +```text + feature/sorting + / +---------------● + \ + feature/student +``` + +Обе ветки на момент создания указывают на один и тот же коммит. + +Теперь в `feature/sorting` доступен весь код, который был добавлен в `feature/student`, в том числе `Student`. + +Чтобы перейти в новую ветку: + +```bash +git checkout feature/sorting +``` + +## Почему важно создавать ветку именно таким образом + +В данном случае `feature/sorting` зависит от кода, находящегося в `feature/student`. + +При этом сами фичи логически разные: + +- `feature/student` — разработка `Student`; +- `feature/sorting` — реализация сортировки; +- `Student` нужен в `feature/sorting` как зависимость для реализации сортировки. + +Поэтому не стоит продолжать разработку сортировки непосредственно в `feature/student`. Лучше создать отдельную ветку от того состояния, где необходимый код уже существует. + +--- + +## Если ветки уже разошлись + +Иногда невозможно создать `feature/sorting` непосредственно от нужного места в истории `feature/student`. + +Например, `feature/sorting` уже была создана раньше: + +```text +A---B---C---D feature/student + \ + E---F---G feature/sorting +``` + +В таком случае можно получить изменения из `feature/student` посредством слияния (merge). + +Находясь в `feature/sorting`, выполняем: + +```bash +git checkout feature/sorting +git merge feature/student +``` + +История станет примерно такой: + +```text +A---B---C---D feature/student + \ \ + E---F---G---M feature/sorting +``` + +Коммит `M` — результат слияния двух веток. + +После этого в `feature/sorting` будут доступны изменения из `feature/student`, в том числе необходимый `Student`. + +## Главное правило + +**Если новая фича зависит от кода из другой ветки, но при этом является самостоятельной по смыслу — создаём для неё отдельную ветку, используя нужную ветку как основу.** + +Если новую ветку можно создать непосредственно от нужного состояния исходной ветки: + +```bash +git checkout feature/student +git branch feature/sorting +``` + +Если ветки уже разошлись и создать её от нужного состояния невозможно: + +```bash +git checkout feature/sorting +git merge feature/student +``` + +Таким образом, мы сохраняем логическое разделение фич и одновременно можем использовать необходимый код из другой ветки. From 52251c658cdf65173ed648240db54e864014e200 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D1=8E=D1=80=D1=8F=D0=B3=D0=B8=D0=BD=20=D0=94=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=BB?= Date: Sun, 23 Aug 2026 19:34:34 +0300 Subject: [PATCH 02/28] feat(sorting): add SortStrategy interface --- app/src/test/java/sorting/SortStrategy.java | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 app/src/test/java/sorting/SortStrategy.java diff --git a/app/src/test/java/sorting/SortStrategy.java b/app/src/test/java/sorting/SortStrategy.java new file mode 100644 index 0000000..f252317 --- /dev/null +++ b/app/src/test/java/sorting/SortStrategy.java @@ -0,0 +1,7 @@ +package sorting; + +import java.util.Comparator; + +public interface SortStrategy { + void sort(MyList list, Comparator comparator); +} \ No newline at end of file From 813b790214bcaa9ce9d47bafe9003ada16abc310 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D1=8E=D1=80=D1=8F=D0=B3=D0=B8=D0=BD=20=D0=94=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=BB?= Date: Sun, 23 Aug 2026 19:36:33 +0300 Subject: [PATCH 03/28] feat(sorting): implement merge sort strategy --- .../test/java/sorting/MergeSortStrategy.java | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 app/src/test/java/sorting/MergeSortStrategy.java diff --git a/app/src/test/java/sorting/MergeSortStrategy.java b/app/src/test/java/sorting/MergeSortStrategy.java new file mode 100644 index 0000000..86655f7 --- /dev/null +++ b/app/src/test/java/sorting/MergeSortStrategy.java @@ -0,0 +1,65 @@ +package sorting; + +import java.util.Comparator; + +public class MergeSortStrategy implements SortStrategy { + + @Override + public void sort(MyList list, Comparator comparator) { + if (list == null || list.size() <= 1) { + return; + } + mergeSort(list, 0, list.size() - 1, comparator); + } + + private void mergeSort(MyList list, int left, int right, Comparator comparator) { + if (left >= right) { + return; + } + int mid = (left + right) / 2; + mergeSort(list, left, mid, comparator); + mergeSort(list, mid + 1, right, comparator); + merge(list, left, mid, right, comparator); + } + + private void merge(MyList list, int left, int mid, int right, Comparator comparator) { + int leftSize = mid - left + 1; + int rightSize = right - mid; + + @SuppressWarnings("unchecked") + T[] leftArray = (T[]) new Object[leftSize]; + @SuppressWarnings("unchecked") + T[] rightArray = (T[]) new Object[rightSize]; + + for (int i = 0; i < leftSize; i++) { + leftArray[i] = list.get(left + i); + } + for (int j = 0; j < rightSize; j++) { + rightArray[j] = list.get(mid + 1 + j); + } + + int i = 0, j = 0, k = left; + + while (i < leftSize && j < rightSize) { + if (comparator.compare(leftArray[i], rightArray[j]) <= 0) { + list.set(k, leftArray[i]); + i++; + } else { + list.set(k, rightArray[j]); + j++; + } + k++; + } + + while (i < leftSize) { + list.set(k, leftArray[i]); + i++; + k++; + } + while (j < rightSize) { + list.set(k, rightArray[j]); + j++; + k++; + } + } +} \ No newline at end of file From edc1e6f84014ea8a961e197db3b6be78c75da3a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D1=8E=D1=80=D1=8F=D0=B3=D0=B8=D0=BD=20=D0=94=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=BB?= Date: Sun, 23 Aug 2026 19:37:29 +0300 Subject: [PATCH 04/28] feat(sorting): add comparator for student group --- app/src/test/java/sorting/StudentGroupComparator.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 app/src/test/java/sorting/StudentGroupComparator.java diff --git a/app/src/test/java/sorting/StudentGroupComparator.java b/app/src/test/java/sorting/StudentGroupComparator.java new file mode 100644 index 0000000..3d40be4 --- /dev/null +++ b/app/src/test/java/sorting/StudentGroupComparator.java @@ -0,0 +1,11 @@ +package sorting; + +import java.util.Comparator; + +public class StudentGroupComparator implements Comparator { + + @Override + public int compare(Student s1, Student s2) { + return Integer.compare(s1.getGroupNumber(), s2.getGroupNumber()); + } +} \ No newline at end of file From f77babf81f6d1720850ce1b5014b726b79976b57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D1=8E=D1=80=D1=8F=D0=B3=D0=B8=D0=BD=20=D0=94=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=BB?= Date: Sun, 23 Aug 2026 19:39:12 +0300 Subject: [PATCH 05/28] feat(sorting): add comparator for average grade --- .../java/sorting/StudentAvarageGradeComparator.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 app/src/test/java/sorting/StudentAvarageGradeComparator.java diff --git a/app/src/test/java/sorting/StudentAvarageGradeComparator.java b/app/src/test/java/sorting/StudentAvarageGradeComparator.java new file mode 100644 index 0000000..46204c2 --- /dev/null +++ b/app/src/test/java/sorting/StudentAvarageGradeComparator.java @@ -0,0 +1,11 @@ +package sorting; + +import java.util.Comparator; + +public class StudentAverageGradeComparator implements Comparator { + + @Override + public int compare(Student s1, Student s2) { + return Double.compare(s1.getAverageGrade(), s2.getAverageGrade()); + } +} \ No newline at end of file From f05c79c3cbcfbd0844b917c80c0f81930a3bdda5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D1=8E=D1=80=D1=8F=D0=B3=D0=B8=D0=BD=20=D0=94=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=BB?= Date: Sun, 23 Aug 2026 19:40:57 +0300 Subject: [PATCH 06/28] feat(sorting): add comparator for record book number --- .../java/sorting/StudentRecordBookComparator.java | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 app/src/test/java/sorting/StudentRecordBookComparator.java diff --git a/app/src/test/java/sorting/StudentRecordBookComparator.java b/app/src/test/java/sorting/StudentRecordBookComparator.java new file mode 100644 index 0000000..22b73e4 --- /dev/null +++ b/app/src/test/java/sorting/StudentRecordBookComparator.java @@ -0,0 +1,11 @@ +package sorting; + +import java.util.Comparator; + +public class StudentRecordBookComparator implements Comparator { + + @Override + public int compare(Student s1, Student s2) { + return Integer.compare(s1.getRecordBookNumber(), s2.getRecordBookNumber()); + } +} \ No newline at end of file From f7443a9d6c2e994409c2d4f30c7b6bd7d64954d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D1=8E=D1=80=D1=8F=D0=B3=D0=B8=D0=BD=20=D0=94=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=BB?= Date: Mon, 24 Aug 2026 18:30:17 +0300 Subject: [PATCH 07/28] fix: correct groupNumber type in StudentGroupComparator --- app/src/test/java/sorting/StudentAvarageGradeComparator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/test/java/sorting/StudentAvarageGradeComparator.java b/app/src/test/java/sorting/StudentAvarageGradeComparator.java index 46204c2..1946fd4 100644 --- a/app/src/test/java/sorting/StudentAvarageGradeComparator.java +++ b/app/src/test/java/sorting/StudentAvarageGradeComparator.java @@ -2,10 +2,10 @@ package sorting; import java.util.Comparator; -public class StudentAverageGradeComparator implements Comparator { +public class StudentAvarageGradeComparator implements Comparator { @Override public int compare(Student s1, Student s2) { - return Double.compare(s1.getAverageGrade(), s2.getAverageGrade()); + return Double.compare(s1.getAvarageGrade(), s2.getAvarageGrade()); } } \ No newline at end of file From dfd6ab9ce658eb76e5989ebda956ae1dcf1cb9cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D1=8E=D1=80=D1=8F=D0=B3=D0=B8=D0=BD=20=D0=94=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=BB?= Date: Mon, 24 Aug 2026 18:54:28 +0300 Subject: [PATCH 08/28] refactor: change groupNumber type from int to String in StudentGroupComparator --- app/src/test/java/sorting/StudentGroupComparator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/test/java/sorting/StudentGroupComparator.java b/app/src/test/java/sorting/StudentGroupComparator.java index 3d40be4..b1efd93 100644 --- a/app/src/test/java/sorting/StudentGroupComparator.java +++ b/app/src/test/java/sorting/StudentGroupComparator.java @@ -5,7 +5,7 @@ import java.util.Comparator; public class StudentGroupComparator implements Comparator { @Override - public int compare(Student s1, Student s2) { + public String compare(Student s1, Student s2) { return Integer.compare(s1.getGroupNumber(), s2.getGroupNumber()); } -} \ No newline at end of file +} From 4d20a59072715cd62d4406b75cdec0f3a05ca2d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BE=D0=BB=D0=BE=D0=B4=D0=B8=D0=BD=20=D0=93=D0=B5?= =?UTF-8?q?=D1=80=D0=BC=D0=B0=D0=BD?= Date: Tue, 25 Aug 2026 23:14:35 +0400 Subject: [PATCH 09/28] refactor: move sorting classes from test to main source set --- .../java => main/java/ru/project}/sorting/MergeSortStrategy.java | 0 .../{test/java => main/java/ru/project}/sorting/SortStrategy.java | 0 .../java/ru/project}/sorting/StudentAvarageGradeComparator.java | 0 .../java/ru/project}/sorting/StudentGroupComparator.java | 0 .../java/ru/project}/sorting/StudentRecordBookComparator.java | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename app/src/{test/java => main/java/ru/project}/sorting/MergeSortStrategy.java (100%) rename app/src/{test/java => main/java/ru/project}/sorting/SortStrategy.java (100%) rename app/src/{test/java => main/java/ru/project}/sorting/StudentAvarageGradeComparator.java (100%) rename app/src/{test/java => main/java/ru/project}/sorting/StudentGroupComparator.java (100%) rename app/src/{test/java => main/java/ru/project}/sorting/StudentRecordBookComparator.java (100%) diff --git a/app/src/test/java/sorting/MergeSortStrategy.java b/app/src/main/java/ru/project/sorting/MergeSortStrategy.java similarity index 100% rename from app/src/test/java/sorting/MergeSortStrategy.java rename to app/src/main/java/ru/project/sorting/MergeSortStrategy.java diff --git a/app/src/test/java/sorting/SortStrategy.java b/app/src/main/java/ru/project/sorting/SortStrategy.java similarity index 100% rename from app/src/test/java/sorting/SortStrategy.java rename to app/src/main/java/ru/project/sorting/SortStrategy.java diff --git a/app/src/test/java/sorting/StudentAvarageGradeComparator.java b/app/src/main/java/ru/project/sorting/StudentAvarageGradeComparator.java similarity index 100% rename from app/src/test/java/sorting/StudentAvarageGradeComparator.java rename to app/src/main/java/ru/project/sorting/StudentAvarageGradeComparator.java diff --git a/app/src/test/java/sorting/StudentGroupComparator.java b/app/src/main/java/ru/project/sorting/StudentGroupComparator.java similarity index 100% rename from app/src/test/java/sorting/StudentGroupComparator.java rename to app/src/main/java/ru/project/sorting/StudentGroupComparator.java diff --git a/app/src/test/java/sorting/StudentRecordBookComparator.java b/app/src/main/java/ru/project/sorting/StudentRecordBookComparator.java similarity index 100% rename from app/src/test/java/sorting/StudentRecordBookComparator.java rename to app/src/main/java/ru/project/sorting/StudentRecordBookComparator.java From 2f9e681b54b6f0794c333813277ab83f5d4d6efa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D1=8E=D1=80=D1=8F=D0=B3=D0=B8=D0=BD=20=D0=94=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=BB?= Date: Wed, 26 Aug 2026 15:57:17 +0300 Subject: [PATCH 10/28] fix: add missing imports for MyList, Student and Comparator in sorting package --- app/src/main/java/ru/project/sorting/MergeSortStrategy.java | 4 +++- app/src/main/java/ru/project/sorting/SortStrategy.java | 3 ++- .../ru/project/sorting/StudentAvarageGradeComparator.java | 3 ++- .../main/java/ru/project/sorting/StudentGroupComparator.java | 3 ++- .../java/ru/project/sorting/StudentRecordBookComparator.java | 3 ++- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/ru/project/sorting/MergeSortStrategy.java b/app/src/main/java/ru/project/sorting/MergeSortStrategy.java index 86655f7..ab22562 100644 --- a/app/src/main/java/ru/project/sorting/MergeSortStrategy.java +++ b/app/src/main/java/ru/project/sorting/MergeSortStrategy.java @@ -1,4 +1,6 @@ -package sorting; +package ru.project.sorting; + +import ru.project.list.MyList; import java.util.Comparator; diff --git a/app/src/main/java/ru/project/sorting/SortStrategy.java b/app/src/main/java/ru/project/sorting/SortStrategy.java index f252317..7dc9983 100644 --- a/app/src/main/java/ru/project/sorting/SortStrategy.java +++ b/app/src/main/java/ru/project/sorting/SortStrategy.java @@ -1,5 +1,6 @@ -package sorting; +package ru.project.sorting; +import ru.project.list.MyList; import java.util.Comparator; public interface SortStrategy { diff --git a/app/src/main/java/ru/project/sorting/StudentAvarageGradeComparator.java b/app/src/main/java/ru/project/sorting/StudentAvarageGradeComparator.java index 1946fd4..a4ca818 100644 --- a/app/src/main/java/ru/project/sorting/StudentAvarageGradeComparator.java +++ b/app/src/main/java/ru/project/sorting/StudentAvarageGradeComparator.java @@ -1,5 +1,6 @@ -package sorting; +package ru.project.sorting; +import ru.project.model.Student; import java.util.Comparator; public class StudentAvarageGradeComparator implements Comparator { diff --git a/app/src/main/java/ru/project/sorting/StudentGroupComparator.java b/app/src/main/java/ru/project/sorting/StudentGroupComparator.java index b1efd93..a43c0e1 100644 --- a/app/src/main/java/ru/project/sorting/StudentGroupComparator.java +++ b/app/src/main/java/ru/project/sorting/StudentGroupComparator.java @@ -1,5 +1,6 @@ -package sorting; +package ru.project.sorting; +import ru.project.model.Student; import java.util.Comparator; public class StudentGroupComparator implements Comparator { diff --git a/app/src/main/java/ru/project/sorting/StudentRecordBookComparator.java b/app/src/main/java/ru/project/sorting/StudentRecordBookComparator.java index 22b73e4..fd72fb4 100644 --- a/app/src/main/java/ru/project/sorting/StudentRecordBookComparator.java +++ b/app/src/main/java/ru/project/sorting/StudentRecordBookComparator.java @@ -1,5 +1,6 @@ -package sorting; +package ru.project.sorting; +import ru.project.model.Student; import java.util.Comparator; public class StudentRecordBookComparator implements Comparator { From 2616603af4256cf4047cf711d88504bec6b264df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D1=8E=D1=80=D1=8F=D0=B3=D0=B8=D0=BD=20=D0=94=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=BB?= Date: Wed, 26 Aug 2026 16:00:37 +0300 Subject: [PATCH 11/28] fix: rename StudentAvarageGradeComparator to StudentAverageGradeComparator --- ...radeComparator.java => StudentAverageGradeComparator.java} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename app/src/main/java/ru/project/sorting/{StudentAvarageGradeComparator.java => StudentAverageGradeComparator.java} (59%) diff --git a/app/src/main/java/ru/project/sorting/StudentAvarageGradeComparator.java b/app/src/main/java/ru/project/sorting/StudentAverageGradeComparator.java similarity index 59% rename from app/src/main/java/ru/project/sorting/StudentAvarageGradeComparator.java rename to app/src/main/java/ru/project/sorting/StudentAverageGradeComparator.java index a4ca818..488aff9 100644 --- a/app/src/main/java/ru/project/sorting/StudentAvarageGradeComparator.java +++ b/app/src/main/java/ru/project/sorting/StudentAverageGradeComparator.java @@ -3,10 +3,10 @@ package ru.project.sorting; import ru.project.model.Student; import java.util.Comparator; -public class StudentAvarageGradeComparator implements Comparator { +public class StudentAverageGradeComparator implements Comparator { @Override public int compare(Student s1, Student s2) { - return Double.compare(s1.getAvarageGrade(), s2.getAvarageGrade()); + return Double.compare(s1.getAverageGrade(), s2.getAverageGrade()); } } \ No newline at end of file From 74effff84e62a94347e272dea393cfbc4f0502cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D1=8E=D1=80=D1=8F=D0=B3=D0=B8=D0=BD=20=D0=94=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=BB?= Date: Thu, 27 Aug 2026 18:30:31 +0300 Subject: [PATCH 12/28] feat: implement BubbleSortStrategy --- .../project/sorting/BubbleSortStrategy.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 app/src/main/java/ru/project/sorting/BubbleSortStrategy.java diff --git a/app/src/main/java/ru/project/sorting/BubbleSortStrategy.java b/app/src/main/java/ru/project/sorting/BubbleSortStrategy.java new file mode 100644 index 0000000..38172db --- /dev/null +++ b/app/src/main/java/ru/project/sorting/BubbleSortStrategy.java @@ -0,0 +1,24 @@ +package ru.project.sorting; + +import ru.project.list.MyList; +import java.util.Comparator; + +public class BubbleSortStrategy implements SortStrategy { + + @Override + public void sort(MyList list, Comparator comparator) { + if (list == null || list.size() <= 1) { + return; + } + int n = list.size(); + for (int i = 0; i < n - 1; i++) { + for (int j = 0; j < n - i - 1; j++) { + if (comparator.compare(list.get(j), list.get(j + 1)) > 0) { + T temp = list.get(j); + list.set(j, list.get(j + 1)); + list.set(j + 1, temp); + } + } + } + } +} \ No newline at end of file From 7a856903108701d64c3c2629577c88a87781f5e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D1=8E=D1=80=D1=8F=D0=B3=D0=B8=D0=BD=20=D0=94=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=BB?= Date: Thu, 27 Aug 2026 18:44:46 +0300 Subject: [PATCH 13/28] feat: add constants for validation, use them in constructor; implement with-methods --- .../main/java/ru/project/student/Student.java | 67 ++++++++++--------- 1 file changed, 36 insertions(+), 31 deletions(-) diff --git a/app/src/main/java/ru/project/student/Student.java b/app/src/main/java/ru/project/student/Student.java index 9dc74e2..be6fa91 100644 --- a/app/src/main/java/ru/project/student/Student.java +++ b/app/src/main/java/ru/project/student/Student.java @@ -3,28 +3,34 @@ package ru.project.student; import java.util.Objects; public class Student { + + public static final double MIN_AVERAGE_GRADE = 0.0; + public static final double MAX_AVERAGE_GRADE = 5.0; + public static final int MIN_RECORD_BOOK_NUMBER = 1; + public static final String GROUP_NUMBER_PATTERN = "^[A-Z][0-9]{2}$"; + private final String groupNumber; private final double averageGrade; private final int recordBookNumber; - // Конструктор с проверками public Student(String groupNumber, double averageGrade, int recordBookNumber) { - // Проверка groupNumber на формат - if (groupNumber == null || !groupNumber.matches("^[A-Z][0-9]{2}$")) { - throw new IllegalArgumentException("Group number must match format: one uppercase letter + two digits (e.g. A12)"); + if (groupNumber == null || !groupNumber.matches(GROUP_NUMBER_PATTERN)) { + throw new IllegalArgumentException( + "Group number must match pattern: " + GROUP_NUMBER_PATTERN); } - if (averageGrade < 0.0 || averageGrade > 5.0) { - throw new IllegalArgumentException("Average grade must be between 0.0 and 5.0"); + if (averageGrade < MIN_AVERAGE_GRADE || averageGrade > MAX_AVERAGE_GRADE) { + throw new IllegalArgumentException( + "Average grade must be between " + MIN_AVERAGE_GRADE + " and " + MAX_AVERAGE_GRADE); } - if (recordBookNumber <= 0) { - throw new IllegalArgumentException("Record book number must be positive"); + if (recordBookNumber < MIN_RECORD_BOOK_NUMBER) { + throw new IllegalArgumentException( + "Record book number must be at least " + MIN_RECORD_BOOK_NUMBER); } this.groupNumber = groupNumber; this.averageGrade = averageGrade; this.recordBookNumber = recordBookNumber; } - // Геттеры — исправлен тип groupNumber (теперь String) public String getGroupNumber() { return groupNumber; } @@ -37,7 +43,6 @@ public class Student { return recordBookNumber; } - // Методы копирования (with-методы) public Student withGroupNumber(String groupNumber) { return new Student(groupNumber, this.averageGrade, this.recordBookNumber); } @@ -50,7 +55,20 @@ public class Student { return new Student(this.groupNumber, this.averageGrade, recordBookNumber); } - @Override + } + + public static double getMaxAverageGrade() { + return MAX_AVERAGE_GRADE; + } + + public static int getMinRecordBookNumber() { + return MIN_RECORD_BOOK_NUMBER; + } + + public static String getGroupNumberPattern() { + return GROUP_NUMBER_PATTERN; + } + public String toString() { return "Student{" + "groupNumber='" + groupNumber + '\'' + @@ -61,8 +79,12 @@ public class Student { @Override public boolean equals(Object obj) { - if (this == obj) return true; - if (obj == null || getClass() != obj.getClass()) return false; + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } Student student = (Student) obj; return Double.compare(averageGrade, student.averageGrade) == 0 && recordBookNumber == student.recordBookNumber @@ -73,21 +95,4 @@ public class Student { public int hashCode() { return Objects.hash(groupNumber, averageGrade, recordBookNumber); } - - // ------------------------ Статические геттеры для границ и формата ------------------------ - public static double getMinAverageGrade() { - return 0.0; - } - - public static double getMaxAverageGrade() { - return 5.0; - } - - public static int getMinRecordBookNumber() { - return 1; - } - - public static String getGroupNumberPattern() { - return "^[A-Z][0-9]{2}$"; - } -} \ No newline at end of file +} From a7a253d7264bf677f320386761bac38931fd91c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=8E=D1=89=D0=B8=D0=BA=20=D0=90=D0=BD?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=B0=D1=81=D0=B8=D1=8F?= Date: Thu, 27 Aug 2026 00:43:53 +0300 Subject: [PATCH 14/28] fix(sorting): update MyList package imports --- app/src/main/java/ru/project/sorting/MergeSortStrategy.java | 2 +- app/src/main/java/ru/project/sorting/SortStrategy.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/ru/project/sorting/MergeSortStrategy.java b/app/src/main/java/ru/project/sorting/MergeSortStrategy.java index ab22562..598f754 100644 --- a/app/src/main/java/ru/project/sorting/MergeSortStrategy.java +++ b/app/src/main/java/ru/project/sorting/MergeSortStrategy.java @@ -1,6 +1,6 @@ package ru.project.sorting; -import ru.project.list.MyList; +import ru.project.collection.MyList; import java.util.Comparator; diff --git a/app/src/main/java/ru/project/sorting/SortStrategy.java b/app/src/main/java/ru/project/sorting/SortStrategy.java index 7dc9983..059d908 100644 --- a/app/src/main/java/ru/project/sorting/SortStrategy.java +++ b/app/src/main/java/ru/project/sorting/SortStrategy.java @@ -1,6 +1,7 @@ package ru.project.sorting; -import ru.project.list.MyList; +import ru.project.collection.MyList; + import java.util.Comparator; public interface SortStrategy { From 4794f03f3cdfefa98209be816fc333cf86a8406d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=8E=D1=89=D0=B8=D0=BA=20=D0=90=D0=BD?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=B0=D1=81=D0=B8=D1=8F?= Date: Thu, 27 Aug 2026 01:14:23 +0300 Subject: [PATCH 15/28] feat(sorting): add even-only merge sort strategy --- .../sorting/EvenOnlyMergeSortStrategy.java | 128 ++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 app/src/main/java/ru/project/sorting/EvenOnlyMergeSortStrategy.java diff --git a/app/src/main/java/ru/project/sorting/EvenOnlyMergeSortStrategy.java b/app/src/main/java/ru/project/sorting/EvenOnlyMergeSortStrategy.java new file mode 100644 index 0000000..a784d7a --- /dev/null +++ b/app/src/main/java/ru/project/sorting/EvenOnlyMergeSortStrategy.java @@ -0,0 +1,128 @@ +package ru.project.sorting; + +import ru.project.collection.MyList; + +import java.util.Comparator; +import java.util.function.ToIntFunction; + +public class EvenOnlyMergeSortStrategy implements SortStrategy { + private final ToIntFunction valueExtractor; + + public EvenOnlyMergeSortStrategy(ToIntFunction valueExtractor) { + this.valueExtractor = valueExtractor; + } + + @Override + public void sort(MyList list, Comparator comparator) { + + if (list == null || list.size() <= 1) { + return; + } + + int evenCount = 0; + + for (int i = 0; i < list.size(); i++) { + T element = list.get(i); + + if (valueExtractor.applyAsInt(element) % 2 == 0) { + evenCount++; + } + } + if (evenCount <= 1) { + return; + } + + @SuppressWarnings("unchecked") + T[] evenElements = (T[]) new Object[evenCount]; + + int[] evenIndexes = new int[evenCount]; + + int evenIndex = 0; + + for (int i = 0; i < list.size(); i++) { + T element = list.get(i); + + if (valueExtractor.applyAsInt(element) % 2 == 0) { + evenElements[evenIndex] = element; + evenIndexes[evenIndex] = i; + evenIndex++; + } + } + mergeSort(evenElements, 0, evenElements.length - 1, comparator); + + for (int i = 0; i < evenIndexes.length; i++) { + list.set(evenIndexes[i], evenElements[i]); + } + } + + private void mergeSort( + T[] elements, + int left, + int right, + Comparator comparator + ) { + if (left >= right) { + return; + } + + int mid = (left + right) / 2; + + mergeSort(elements, left, mid, comparator); + mergeSort(elements, mid + 1, right, comparator); + + merge(elements, left, mid, right, comparator); + } + private void merge( + T[] elements, + int left, + int mid, + int right, + Comparator comparator + ) { + int leftSize = mid - left + 1; + int rightSize = right - mid; + + @SuppressWarnings("unchecked") + T[] leftArray = (T[]) new Object[leftSize]; + + @SuppressWarnings("unchecked") + T[] rightArray = (T[]) new Object[rightSize]; + + for (int i = 0; i < leftSize; i++) { + leftArray[i] = elements[left + i]; + } + + for (int j = 0; j < rightSize; j++) { + rightArray[j] = elements[mid + 1 + j]; + } + + int i = 0; + int j = 0; + int k = left; + + while (i < leftSize && j < rightSize) { + if (comparator.compare(leftArray[i], rightArray[j]) <= 0) { + elements[k] = leftArray[i]; + i++; + } else { + elements[k] = rightArray[j]; + j++; + } + + k++; + } + + while (i < leftSize) { + elements[k] = leftArray[i]; + i++; + k++; + } + + while (j < rightSize) { + elements[k] = rightArray[j]; + j++; + k++; + } + } +} + From a9f578ad363dacf59018c76f2dfbec5886688524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=8E=D1=89=D0=B8=D0=BA=20=D0=90=D0=BD?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=B0=D1=81=D0=B8=D1=8F?= Date: Thu, 27 Aug 2026 23:09:20 +0300 Subject: [PATCH 16/28] fix(collection): add package declaration to MyLinkedList --- app/src/main/java/ru/project/collection/MyLinkedList.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/ru/project/collection/MyLinkedList.java b/app/src/main/java/ru/project/collection/MyLinkedList.java index 23b2b75..270689c 100644 --- a/app/src/main/java/ru/project/collection/MyLinkedList.java +++ b/app/src/main/java/ru/project/collection/MyLinkedList.java @@ -1,3 +1,4 @@ +package ru.project.collection; import java.util.Arrays; public class MyLinkedList implements MyList { From 62f45cea65b3088a6c65606531cc4efe40bc5cf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=8E=D1=89=D0=B8=D0=BA=20=D0=90=D0=BD?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=B0=D1=81=D0=B8=D1=8F?= Date: Thu, 27 Aug 2026 23:54:34 +0300 Subject: [PATCH 17/28] fix(sorting): update Student imports --- .../java/ru/project/sorting/StudentAverageGradeComparator.java | 2 +- .../main/java/ru/project/sorting/StudentGroupComparator.java | 2 +- .../java/ru/project/sorting/StudentRecordBookComparator.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/ru/project/sorting/StudentAverageGradeComparator.java b/app/src/main/java/ru/project/sorting/StudentAverageGradeComparator.java index 488aff9..fea72f6 100644 --- a/app/src/main/java/ru/project/sorting/StudentAverageGradeComparator.java +++ b/app/src/main/java/ru/project/sorting/StudentAverageGradeComparator.java @@ -1,6 +1,6 @@ package ru.project.sorting; -import ru.project.model.Student; +import ru.project.student.Student; import java.util.Comparator; public class StudentAverageGradeComparator implements Comparator { diff --git a/app/src/main/java/ru/project/sorting/StudentGroupComparator.java b/app/src/main/java/ru/project/sorting/StudentGroupComparator.java index a43c0e1..b23496e 100644 --- a/app/src/main/java/ru/project/sorting/StudentGroupComparator.java +++ b/app/src/main/java/ru/project/sorting/StudentGroupComparator.java @@ -1,6 +1,6 @@ package ru.project.sorting; -import ru.project.model.Student; +import ru.project.student.Student; import java.util.Comparator; public class StudentGroupComparator implements Comparator { diff --git a/app/src/main/java/ru/project/sorting/StudentRecordBookComparator.java b/app/src/main/java/ru/project/sorting/StudentRecordBookComparator.java index fd72fb4..0e4a714 100644 --- a/app/src/main/java/ru/project/sorting/StudentRecordBookComparator.java +++ b/app/src/main/java/ru/project/sorting/StudentRecordBookComparator.java @@ -1,6 +1,6 @@ package ru.project.sorting; -import ru.project.model.Student; +import ru.project.student.Student; import java.util.Comparator; public class StudentRecordBookComparator implements Comparator { From da8a42d89523e16a440d49fda4bbf78c42d9aaf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=8E=D1=89=D0=B8=D0=BA=20=D0=90=D0=BD?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=B0=D1=81=D0=B8=D1=8F?= Date: Fri, 28 Aug 2026 00:07:16 +0300 Subject: [PATCH 18/28] test(sorting): add even-only merge sort tests --- .../EvenOnlyMergeSortStrategyTest.java | 149 ++++++++++++++++++ 1 file changed, 149 insertions(+) create mode 100644 app/src/test/java/ru/project/sorting/EvenOnlyMergeSortStrategyTest.java diff --git a/app/src/test/java/ru/project/sorting/EvenOnlyMergeSortStrategyTest.java b/app/src/test/java/ru/project/sorting/EvenOnlyMergeSortStrategyTest.java new file mode 100644 index 0000000..b423cba --- /dev/null +++ b/app/src/test/java/ru/project/sorting/EvenOnlyMergeSortStrategyTest.java @@ -0,0 +1,149 @@ +package ru.project.sorting; + +import org.junit.jupiter.api.Test; +import ru.project.collection.MyLinkedList; +import ru.project.collection.MyList; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class EvenOnlyMergeSortStrategyTest { + + @Test + void shouldSortOnlyEvenElements() { + MyList list = new MyLinkedList<>(); + + list.add(7); + list.add(8); + list.add(3); + list.add(2); + list.add(5); + list.add(4); + + EvenOnlyMergeSortStrategy strategy = + new EvenOnlyMergeSortStrategy<>(value -> value); + + strategy.sort(list, Integer::compare); + + assertEquals(7, list.get(0)); + assertEquals(2, list.get(1)); + assertEquals(3, list.get(2)); + assertEquals(4, list.get(3)); + assertEquals(5, list.get(4)); + assertEquals(8, list.get(5)); + + assertEquals(6, list.size()); + } + + @Test + void shouldKeepAllOddElementsUnchanged() { + MyList list = new MyLinkedList<>(); + + list.add(7); + list.add(3); + list.add(5); + list.add(1); + + EvenOnlyMergeSortStrategy strategy = + new EvenOnlyMergeSortStrategy<>(value -> value); + + strategy.sort(list, Integer::compare); + + assertEquals(7, list.get(0)); + assertEquals(3, list.get(1)); + assertEquals(5, list.get(2)); + assertEquals(1, list.get(3)); + } + + @Test + void shouldSortAllEvenElements() { + MyList list = new MyLinkedList<>(); + + list.add(8); + list.add(2); + list.add(6); + list.add(4); + + EvenOnlyMergeSortStrategy strategy = + new EvenOnlyMergeSortStrategy<>(value -> value); + + strategy.sort(list, Integer::compare); + + assertEquals(2, list.get(0)); + assertEquals(4, list.get(1)); + assertEquals(6, list.get(2)); + assertEquals(8, list.get(3)); + } + + @Test + void shouldKeepSingleElementUnchanged() { + MyList list = new MyLinkedList<>(); + + list.add(4); + + EvenOnlyMergeSortStrategy strategy = + new EvenOnlyMergeSortStrategy<>(value -> value); + + strategy.sort(list, Integer::compare); + + assertEquals(4, list.get(0)); + assertEquals(1, list.size()); + } + + @Test + void shouldHandleEmptyList() { + MyList list = new MyLinkedList<>(); + + EvenOnlyMergeSortStrategy strategy = + new EvenOnlyMergeSortStrategy<>(value -> value); + + strategy.sort(list, Integer::compare); + + assertEquals(0, list.size()); + } + + @Test + void shouldUseValueExtractorToDetermineEvenElements() { + MyList list = new MyLinkedList<>(); + + list.add(4); + list.add(3); + list.add(2); + list.add(1); + + EvenOnlyMergeSortStrategy strategy = + new EvenOnlyMergeSortStrategy<>(value -> value + 1); + + strategy.sort(list, Integer::compare); + + assertEquals(4, list.get(0)); + assertEquals(1, list.get(1)); + assertEquals(2, list.get(2)); + assertEquals(3, list.get(3)); + } + + @Test + void shouldUseProvidedComparator() { + MyList list = new MyLinkedList<>(); + + list.add(7); + list.add(2); + list.add(3); + list.add(8); + list.add(5); + list.add(4); + + EvenOnlyMergeSortStrategy strategy = + new EvenOnlyMergeSortStrategy<>(value -> value); + + strategy.sort(list, (first, second) -> Integer.compare(second, first)); + + assertEquals(7, list.get(0)); + assertEquals(8, list.get(1)); + assertEquals(3, list.get(2)); + assertEquals(4, list.get(3)); + assertEquals(5, list.get(4)); + assertEquals(2, list.get(5)); + } +} + + From 9a670a7380280a0adebccb0d152cedc5e593373b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D1=8E=D1=80=D1=8F=D0=B3=D0=B8=D0=BD=20=D0=94=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=BB?= Date: Thu, 27 Aug 2026 18:51:52 +0300 Subject: [PATCH 19/28] feat: add EvenOnlyMergeSortStrategy --- .../sorting/EvenOnlyMergeSortStrategy.java | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 app/src/main/java/ru/project/sorting/EvenOnlyMergeSortStrategy.java diff --git a/app/src/main/java/ru/project/sorting/EvenOnlyMergeSortStrategy.java b/app/src/main/java/ru/project/sorting/EvenOnlyMergeSortStrategy.java new file mode 100644 index 0000000..dea539e --- /dev/null +++ b/app/src/main/java/ru/project/sorting/EvenOnlyMergeSortStrategy.java @@ -0,0 +1,84 @@ +package ru.project.sorting; + +import ru.project.list.MyList; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.function.ToIntFunction; + +public class EvenOnlyMergeSortStrategy implements SortStrategy { + + private final ToIntFunction valueExtractor; + + public EvenOnlyMergeSortStrategy(ToIntFunction valueExtractor) { + this.valueExtractor = valueExtractor; + } + + @Override + public void sort(MyList list, Comparator comparator) { + if (list == null || list.size() <= 1) { + return; + } + + List evenIndices = new ArrayList<>(); + List evenElements = new ArrayList<>(); + + for (int i = 0; i < list.size(); i++) { + T element = list.get(i); + int value = valueExtractor.applyAsInt(element); + if (value % 2 == 0) { + evenIndices.add(i); + evenElements.add(element); + } + } + + if (evenElements.size() <= 1) { + return; + } + + List sortedEven = mergeSort(evenElements, comparator); + + for (int j = 0; j < evenIndices.size(); j++) { + list.set(evenIndices.get(j), sortedEven.get(j)); + } + } + + private List mergeSort(List list, Comparator comparator) { + if (list.size() <= 1) { + return list; + } + + int mid = list.size() / 2; + List left = mergeSort(list.subList(0, mid), comparator); + List right = mergeSort(list.subList(mid, list.size()), comparator); + + return merge(left, right, comparator); + } + + private List merge(List left, List right, Comparator comparator) { + List result = new ArrayList<>(); + int i = 0, j = 0; + + while (i < left.size() && j < right.size()) { + if (comparator.compare(left.get(i), right.get(j)) <= 0) { + result.add(left.get(i)); + i++; + } else { + result.add(right.get(j)); + j++; + } + } + + while (i < left.size()) { + result.add(left.get(i)); + i++; + } + + while (j < right.size()) { + result.add(right.get(j)); + j++; + } + + return result; + } +} \ No newline at end of file From 80ebc71366a1e45234b0b0be0fda4d6a694c3456 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BE=D0=BB=D0=BE=D0=B4=D0=B8=D0=BD=20=D0=93=D0=B5?= =?UTF-8?q?=D1=80=D0=BC=D0=B0=D0=BD?= Date: Fri, 28 Aug 2026 11:53:00 +0400 Subject: [PATCH 20/28] test: add comprehensive unit tests for Student model --- .../java/ru/project/student/StudentTest.java | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 app/src/main/java/ru/project/student/StudentTest.java diff --git a/app/src/main/java/ru/project/student/StudentTest.java b/app/src/main/java/ru/project/student/StudentTest.java new file mode 100644 index 0000000..cdce6d8 --- /dev/null +++ b/app/src/main/java/ru/project/student/StudentTest.java @@ -0,0 +1,139 @@ +package ru.project.student; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +class StudentTest { + + @Test + void testValidStudentCreation() { + Student student = new Student("A12", 4.5, 12345); + assertEquals("A12", student.getGroupNumber()); + assertEquals(4.5, student.getAverageGrade()); + assertEquals(12345, student.getRecordBookNumber()); + } + + @Test + void testValidGroupNumbers() { + assertDoesNotThrow(() -> new Student("A12", 4.5, 1)); + assertDoesNotThrow(() -> new Student("B32", 4.5, 1)); + assertDoesNotThrow(() -> new Student("Z00", 4.5, 1)); + } + + @Test + void testInvalidGroupNumbers() { + assertThrows(IllegalArgumentException.class, () -> new Student("a12", 4.5, 1)); + assertThrows(IllegalArgumentException.class, () -> new Student("A1", 4.5, 1)); + assertThrows(IllegalArgumentException.class, () -> new Student("A123", 4.5, 1)); + assertThrows(IllegalArgumentException.class, () -> new Student("AA1", 4.5, 1)); + assertThrows(IllegalArgumentException.class, () -> new Student("а1А", 4.5, 1)); + assertThrows(IllegalArgumentException.class, () -> new Student("аа!!а123", 4.5, 1)); + assertThrows(IllegalArgumentException.class, () -> new Student("23фи!12", 4.5, 1)); + assertThrows(IllegalArgumentException.class, () -> new Student("№№###*()", 4.5, 1)); + } + + @Test + void testValidAverageGrades() { + assertDoesNotThrow(() -> new Student("A12", 0.0, 1)); + assertDoesNotThrow(() -> new Student("A12", 5.0, 1)); + } + + @Test + void testInvalidAverageGrades() { + assertThrows(IllegalArgumentException.class, () -> new Student("A12", -1.0, 1)); + assertThrows(IllegalArgumentException.class, () -> new Student("A12", 6.0, 1)); + } + + @Test + void testValidRecordBookNumbers() { + assertDoesNotThrow(() -> new Student("A12", 4.5, 1)); + assertDoesNotThrow(() -> new Student("A12", 4.5, 12345)); + } + + @Test + void testInvalidRecordBookNumbers() { + assertThrows(IllegalArgumentException.class, () -> new Student("A12", 4.5, 0)); + assertThrows(IllegalArgumentException.class, () -> new Student("A12", 4.5, -1)); + } + + @Test + void testWithGroupNumber() { + Student original = new Student("A12", 4.5, 12345); + Student updated = original.withGroupNumber("B32"); + + assertNotSame(original, updated); + assertEquals("B32", updated.getGroupNumber()); + assertEquals(4.5, updated.getAverageGrade()); + assertEquals(12345, updated.getRecordBookNumber()); + + assertEquals("A12", original.getGroupNumber()); + } + + @Test + void testWithAverageGrade() { + Student original = new Student("A12", 4.5, 12345); + Student updated = original.withAverageGrade(4.8); + + assertNotSame(original, updated); + assertEquals(4.8, updated.getAverageGrade()); + assertEquals("A12", updated.getGroupNumber()); + assertEquals(12345, updated.getRecordBookNumber()); + + assertEquals(4.5, original.getAverageGrade()); + } + + @Test + void testWithRecordBookNumber() { + Student original = new Student("A12", 4.5, 12345); + Student updated = original.withRecordBookNumber(99999); + + assertNotSame(original, updated); + assertEquals(99999, updated.getRecordBookNumber()); + assertEquals("A12", updated.getGroupNumber()); + assertEquals(4.5, updated.getAverageGrade()); + + assertEquals(12345, original.getRecordBookNumber()); + } + + @Test + void testWithInvalidGroupNumber() { + Student original = new Student("A12", 4.5, 12345); + assertThrows(IllegalArgumentException.class, + () -> original.withGroupNumber("a12")); + assertEquals("A12", original.getGroupNumber()); // не изменился + } + + @Test + void testWithInvalidAverageGrade() { + Student original = new Student("A12", 4.5, 12345); + assertThrows(IllegalArgumentException.class, + () -> original.withAverageGrade(6.0)); + assertEquals(4.5, original.getAverageGrade()); + } + + @Test + void testWithInvalidRecordBookNumber() { + Student original = new Student("A12", 4.5, 12345); + assertThrows(IllegalArgumentException.class, + () -> original.withRecordBookNumber(0)); + assertEquals(12345, original.getRecordBookNumber()); + } + + @Test + void testEqualsAndHashCode() { + Student s1 = new Student("A12", 4.5, 12345); + Student s2 = new Student("A12", 4.5, 12345); + Student s3 = new Student("B32", 4.5, 12345); + Student s4 = new Student("A12", 4.8, 12345); + Student s5 = new Student("A12", 4.5, 99999); + + assertEquals(s1, s2); + assertEquals(s1.hashCode(), s2.hashCode()); + + assertNotEquals(s1, s3); + assertNotEquals(s1, s4); + assertNotEquals(s1, s5); + assertNotEquals(s1, null); + assertNotEquals(s1, "some string"); + } +} \ No newline at end of file From daa658347064bba0cff87a777e077b905c632bc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BE=D0=BB=D0=BE=D0=B4=D0=B8=D0=BD=20=D0=93=D0=B5?= =?UTF-8?q?=D1=80=D0=BC=D0=B0=D0=BD?= Date: Fri, 28 Aug 2026 12:06:00 +0400 Subject: [PATCH 21/28] test: reorganize Student tests and fix duplicate test file --- .../main/java/ru/project/student/Student.java | 2 - .../java/ru/project/student/StudentTest.java | 139 ------------ .../java/ru/project/student/StudentTest.java | 209 ++++++++---------- 3 files changed, 93 insertions(+), 257 deletions(-) delete mode 100644 app/src/main/java/ru/project/student/StudentTest.java diff --git a/app/src/main/java/ru/project/student/Student.java b/app/src/main/java/ru/project/student/Student.java index be6fa91..b5d64d2 100644 --- a/app/src/main/java/ru/project/student/Student.java +++ b/app/src/main/java/ru/project/student/Student.java @@ -55,8 +55,6 @@ public class Student { return new Student(this.groupNumber, this.averageGrade, recordBookNumber); } - } - public static double getMaxAverageGrade() { return MAX_AVERAGE_GRADE; } diff --git a/app/src/main/java/ru/project/student/StudentTest.java b/app/src/main/java/ru/project/student/StudentTest.java deleted file mode 100644 index cdce6d8..0000000 --- a/app/src/main/java/ru/project/student/StudentTest.java +++ /dev/null @@ -1,139 +0,0 @@ -package ru.project.student; - -import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; - -class StudentTest { - - @Test - void testValidStudentCreation() { - Student student = new Student("A12", 4.5, 12345); - assertEquals("A12", student.getGroupNumber()); - assertEquals(4.5, student.getAverageGrade()); - assertEquals(12345, student.getRecordBookNumber()); - } - - @Test - void testValidGroupNumbers() { - assertDoesNotThrow(() -> new Student("A12", 4.5, 1)); - assertDoesNotThrow(() -> new Student("B32", 4.5, 1)); - assertDoesNotThrow(() -> new Student("Z00", 4.5, 1)); - } - - @Test - void testInvalidGroupNumbers() { - assertThrows(IllegalArgumentException.class, () -> new Student("a12", 4.5, 1)); - assertThrows(IllegalArgumentException.class, () -> new Student("A1", 4.5, 1)); - assertThrows(IllegalArgumentException.class, () -> new Student("A123", 4.5, 1)); - assertThrows(IllegalArgumentException.class, () -> new Student("AA1", 4.5, 1)); - assertThrows(IllegalArgumentException.class, () -> new Student("а1А", 4.5, 1)); - assertThrows(IllegalArgumentException.class, () -> new Student("аа!!а123", 4.5, 1)); - assertThrows(IllegalArgumentException.class, () -> new Student("23фи!12", 4.5, 1)); - assertThrows(IllegalArgumentException.class, () -> new Student("№№###*()", 4.5, 1)); - } - - @Test - void testValidAverageGrades() { - assertDoesNotThrow(() -> new Student("A12", 0.0, 1)); - assertDoesNotThrow(() -> new Student("A12", 5.0, 1)); - } - - @Test - void testInvalidAverageGrades() { - assertThrows(IllegalArgumentException.class, () -> new Student("A12", -1.0, 1)); - assertThrows(IllegalArgumentException.class, () -> new Student("A12", 6.0, 1)); - } - - @Test - void testValidRecordBookNumbers() { - assertDoesNotThrow(() -> new Student("A12", 4.5, 1)); - assertDoesNotThrow(() -> new Student("A12", 4.5, 12345)); - } - - @Test - void testInvalidRecordBookNumbers() { - assertThrows(IllegalArgumentException.class, () -> new Student("A12", 4.5, 0)); - assertThrows(IllegalArgumentException.class, () -> new Student("A12", 4.5, -1)); - } - - @Test - void testWithGroupNumber() { - Student original = new Student("A12", 4.5, 12345); - Student updated = original.withGroupNumber("B32"); - - assertNotSame(original, updated); - assertEquals("B32", updated.getGroupNumber()); - assertEquals(4.5, updated.getAverageGrade()); - assertEquals(12345, updated.getRecordBookNumber()); - - assertEquals("A12", original.getGroupNumber()); - } - - @Test - void testWithAverageGrade() { - Student original = new Student("A12", 4.5, 12345); - Student updated = original.withAverageGrade(4.8); - - assertNotSame(original, updated); - assertEquals(4.8, updated.getAverageGrade()); - assertEquals("A12", updated.getGroupNumber()); - assertEquals(12345, updated.getRecordBookNumber()); - - assertEquals(4.5, original.getAverageGrade()); - } - - @Test - void testWithRecordBookNumber() { - Student original = new Student("A12", 4.5, 12345); - Student updated = original.withRecordBookNumber(99999); - - assertNotSame(original, updated); - assertEquals(99999, updated.getRecordBookNumber()); - assertEquals("A12", updated.getGroupNumber()); - assertEquals(4.5, updated.getAverageGrade()); - - assertEquals(12345, original.getRecordBookNumber()); - } - - @Test - void testWithInvalidGroupNumber() { - Student original = new Student("A12", 4.5, 12345); - assertThrows(IllegalArgumentException.class, - () -> original.withGroupNumber("a12")); - assertEquals("A12", original.getGroupNumber()); // не изменился - } - - @Test - void testWithInvalidAverageGrade() { - Student original = new Student("A12", 4.5, 12345); - assertThrows(IllegalArgumentException.class, - () -> original.withAverageGrade(6.0)); - assertEquals(4.5, original.getAverageGrade()); - } - - @Test - void testWithInvalidRecordBookNumber() { - Student original = new Student("A12", 4.5, 12345); - assertThrows(IllegalArgumentException.class, - () -> original.withRecordBookNumber(0)); - assertEquals(12345, original.getRecordBookNumber()); - } - - @Test - void testEqualsAndHashCode() { - Student s1 = new Student("A12", 4.5, 12345); - Student s2 = new Student("A12", 4.5, 12345); - Student s3 = new Student("B32", 4.5, 12345); - Student s4 = new Student("A12", 4.8, 12345); - Student s5 = new Student("A12", 4.5, 99999); - - assertEquals(s1, s2); - assertEquals(s1.hashCode(), s2.hashCode()); - - assertNotEquals(s1, s3); - assertNotEquals(s1, s4); - assertNotEquals(s1, s5); - assertNotEquals(s1, null); - assertNotEquals(s1, "some string"); - } -} \ No newline at end of file diff --git a/app/src/test/java/ru/project/student/StudentTest.java b/app/src/test/java/ru/project/student/StudentTest.java index e9a7434..09cf2e7 100644 --- a/app/src/test/java/ru/project/student/StudentTest.java +++ b/app/src/test/java/ru/project/student/StudentTest.java @@ -2,167 +2,144 @@ package ru.project.student; import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotSame; class StudentTest { - @Test - void shouldCreateValidStudent() { - Student student = new StudentBuilder() - .setGroupNumber("101") - .setAverageGrade(4.5) - .setRecordBookNumber("12345") - .build(); - assertEquals("101", student.getGroupNumber()); + @Test + void testValidStudentCreation() { + Student student = new Student("A12", 4.5, 12345); + assertEquals("A12", student.getGroupNumber()); assertEquals(4.5, student.getAverageGrade()); - assertEquals("12345", student.getRecordBookNumber()); + assertEquals(12345, student.getRecordBookNumber()); } @Test - void shouldThrowExceptionWhenGroupNumberIsEmpty() { - assertThrows(IllegalArgumentException.class, () -> { - new StudentBuilder() - .setGroupNumber("") - .setAverageGrade(4.5) - .setRecordBookNumber("12345") - .build(); - }); + void testValidGroupNumbers() { + assertDoesNotThrow(() -> new Student("A12", 4.5, 1)); + assertDoesNotThrow(() -> new Student("B32", 4.5, 1)); + assertDoesNotThrow(() -> new Student("Z00", 4.5, 1)); } @Test - void shouldThrowExceptionWhenAverageGradeIsGreaterThanFive() { - assertThrows(IllegalArgumentException.class, () -> { - new StudentBuilder() - .setGroupNumber("101") - .setAverageGrade(6.0) - .setRecordBookNumber("12345") - .build(); - }); + void testInvalidGroupNumbers() { + assertThrows(IllegalArgumentException.class, () -> new Student("a12", 4.5, 1)); + assertThrows(IllegalArgumentException.class, () -> new Student("A1", 4.5, 1)); + assertThrows(IllegalArgumentException.class, () -> new Student("A123", 4.5, 1)); + assertThrows(IllegalArgumentException.class, () -> new Student("AA1", 4.5, 1)); + assertThrows(IllegalArgumentException.class, () -> new Student("а1А", 4.5, 1)); + assertThrows(IllegalArgumentException.class, () -> new Student("аа!!а123", 4.5, 1)); + assertThrows(IllegalArgumentException.class, () -> new Student("23фи!12", 4.5, 1)); + assertThrows(IllegalArgumentException.class, () -> new Student("№№###*()", 4.5, 1)); } @Test - void shouldThrowExceptionWhenAverageGradeIsLessThanZero() { - assertThrows(IllegalArgumentException.class, () -> { - new StudentBuilder() - .setGroupNumber("101") - .setAverageGrade(-1.0) - .setRecordBookNumber("12345") - .build(); - }); + void testValidAverageGrades() { + assertDoesNotThrow(() -> new Student("A12", 0.0, 1)); + assertDoesNotThrow(() -> new Student("A12", 5.0, 1)); } @Test - void shouldCreateStudentWhenAverageGradeIsZero() { - Student student = new StudentBuilder() - .setGroupNumber("101") - .setAverageGrade(0.0) - .setRecordBookNumber("12345") - .build(); - - assertEquals(0.0, student.getAverageGrade()); + void testInvalidAverageGrades() { + assertThrows(IllegalArgumentException.class, () -> new Student("A12", -1.0, 1)); + assertThrows(IllegalArgumentException.class, () -> new Student("A12", 6.0, 1)); } @Test - void shouldCreateStudentWhenAverageGradeIsFive() { - Student student = new StudentBuilder() - .setGroupNumber("101") - .setAverageGrade(5.0) - .setRecordBookNumber("12345") - .build(); - - assertEquals(5.0, student.getAverageGrade()); + void testValidRecordBookNumbers() { + assertDoesNotThrow(() -> new Student("A12", 4.5, 1)); + assertDoesNotThrow(() -> new Student("A12", 4.5, 12345)); } @Test - void shouldThrowExceptionWhenRecordBookNumberIsEmpty() { - assertThrows(IllegalArgumentException.class, () -> { - new StudentBuilder() - .setGroupNumber("101") - .setAverageGrade(4.5) - .setRecordBookNumber("") - .build(); - }); + void testInvalidRecordBookNumbers() { + assertThrows(IllegalArgumentException.class, () -> new Student("A12", 4.5, 0)); + assertThrows(IllegalArgumentException.class, () -> new Student("A12", 4.5, -1)); } @Test - void shouldThrowExceptionWhenGroupNumberIsNull() { - assertThrows(IllegalArgumentException.class, () -> { - new StudentBuilder() - .setGroupNumber(null) - .setAverageGrade(4.5) - .setRecordBookNumber("12345") - .build(); - }); + void testWithGroupNumber() { + Student original = new Student("A12", 4.5, 12345); + Student updated = original.withGroupNumber("B32"); + + assertNotSame(original, updated); + assertEquals("B32", updated.getGroupNumber()); + assertEquals(4.5, updated.getAverageGrade()); + assertEquals(12345, updated.getRecordBookNumber()); + + assertEquals("A12", original.getGroupNumber()); } @Test - void shouldThrowExceptionWhenGroupNumberIsBlank() { - assertThrows(IllegalArgumentException.class, () -> { - new StudentBuilder() - .setGroupNumber(" ") - .setAverageGrade(4.5) - .setRecordBookNumber("12345") - .build(); - }); + void testWithAverageGrade() { + Student original = new Student("A12", 4.5, 12345); + Student updated = original.withAverageGrade(4.8); + + assertNotSame(original, updated); + assertEquals(4.8, updated.getAverageGrade()); + assertEquals("A12", updated.getGroupNumber()); + assertEquals(12345, updated.getRecordBookNumber()); + + assertEquals(4.5, original.getAverageGrade()); } @Test - void shouldThrowExceptionWhenRecordBookNumberIsNull() { - assertThrows(IllegalArgumentException.class, () -> { - new StudentBuilder() - .setGroupNumber("101") - .setAverageGrade(4.5) - .setRecordBookNumber(null) - .build(); - }); + void testWithRecordBookNumber() { + Student original = new Student("A12", 4.5, 12345); + Student updated = original.withRecordBookNumber(99999); + + assertNotSame(original, updated); + assertEquals(99999, updated.getRecordBookNumber()); + assertEquals("A12", updated.getGroupNumber()); + assertEquals(4.5, updated.getAverageGrade()); + + assertEquals(12345, original.getRecordBookNumber()); } @Test - void shouldThrowExceptionWhenRecordBookNumberIsBlank() { - assertThrows(IllegalArgumentException.class, () -> { - new StudentBuilder() - .setGroupNumber("101") - .setAverageGrade(4.5) - .setRecordBookNumber(" ") - .build(); - }); + void testWithInvalidGroupNumber() { + Student original = new Student("A12", 4.5, 12345); + assertThrows(IllegalArgumentException.class, + () -> original.withGroupNumber("a12")); + assertEquals("A12", original.getGroupNumber()); // не изменился } @Test - void shouldReturnTrueWhenStudentsAreEqual() { - Student student1 = new StudentBuilder() - .setGroupNumber("101") - .setAverageGrade(4.5) - .setRecordBookNumber("12345") - .build(); - - Student student2 = new StudentBuilder() - .setGroupNumber("101") - .setAverageGrade(4.5) - .setRecordBookNumber("12345") - .build(); - - assertEquals(student1, student2); - assertEquals(student1.hashCode(), student2.hashCode()); + void testWithInvalidAverageGrade() { + Student original = new Student("A12", 4.5, 12345); + assertThrows(IllegalArgumentException.class, + () -> original.withAverageGrade(6.0)); + assertEquals(4.5, original.getAverageGrade()); } @Test - void shouldReturnFalseWhenStudentsAreDifferent() { - Student student1 = new StudentBuilder() - .setGroupNumber("101") - .setAverageGrade(4.5) - .setRecordBookNumber("12345") - .build(); + void testWithInvalidRecordBookNumber() { + Student original = new Student("A12", 4.5, 12345); + assertThrows(IllegalArgumentException.class, + () -> original.withRecordBookNumber(0)); + assertEquals(12345, original.getRecordBookNumber()); + } - Student student2 = new StudentBuilder() - .setGroupNumber("102") - .setAverageGrade(4.5) - .setRecordBookNumber("12345") - .build(); + @Test + void testEqualsAndHashCode() { + Student s1 = new Student("A12", 4.5, 12345); + Student s2 = new Student("A12", 4.5, 12345); + Student s3 = new Student("B32", 4.5, 12345); + Student s4 = new Student("A12", 4.8, 12345); + Student s5 = new Student("A12", 4.5, 99999); - assertNotEquals(student1, student2); + assertEquals(s1, s2); + assertEquals(s1.hashCode(), s2.hashCode()); + + assertNotEquals(s1, s3); + assertNotEquals(s1, s4); + assertNotEquals(s1, s5); + assertNotEquals(s1, null); + assertNotEquals(s1, "some string"); } } From e47732b9ec2d1758912b53de8445418d16248fc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BE=D0=BB=D0=BE=D0=B4=D0=B8=D0=BD=20=D0=93=D0=B5?= =?UTF-8?q?=D1=80=D0=BC=D0=B0=D0=BD?= Date: Fri, 28 Aug 2026 12:14:10 +0400 Subject: [PATCH 22/28] fix: correct student group comparator --- .../main/java/ru/project/sorting/StudentGroupComparator.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/ru/project/sorting/StudentGroupComparator.java b/app/src/main/java/ru/project/sorting/StudentGroupComparator.java index b23496e..75cae82 100644 --- a/app/src/main/java/ru/project/sorting/StudentGroupComparator.java +++ b/app/src/main/java/ru/project/sorting/StudentGroupComparator.java @@ -6,7 +6,7 @@ import java.util.Comparator; public class StudentGroupComparator implements Comparator { @Override - public String compare(Student s1, Student s2) { - return Integer.compare(s1.getGroupNumber(), s2.getGroupNumber()); + public int compare(Student s1, Student s2) { + return s1.getGroupNumber().compareTo(s2.getGroupNumber()); } } From 18e1608103f9c116fbb912a1bfe6af6878874c9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D1=8E=D1=80=D1=8F=D0=B3=D0=B8=D0=BD=20=D0=94=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=BB?= Date: Fri, 28 Aug 2026 18:17:53 +0300 Subject: [PATCH 23/28] test: add comprehensive tests for all SortStrategy implementations --- .../ru/project/Sorting/SortStrategyTest.java | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 app/src/test/java/ru/project/Sorting/SortStrategyTest.java diff --git a/app/src/test/java/ru/project/Sorting/SortStrategyTest.java b/app/src/test/java/ru/project/Sorting/SortStrategyTest.java new file mode 100644 index 0000000..6e0472c --- /dev/null +++ b/app/src/test/java/ru/project/Sorting/SortStrategyTest.java @@ -0,0 +1,163 @@ +package ru.project.sorting; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import ru.project.list.MyList; +import ru.project.list.MyLinkedList; +import ru.project.student.Student; + +import java.util.Comparator; + +import static org.junit.jupiter.api.Assertions.*; + +class SortStrategyTest { + + private MyList students; + private final Comparator groupComparator = new StudentGroupComparator(); + private final Comparator gradeComparator = new StudentAverageGradeComparator(); + private final Comparator recordComparator = new StudentRecordBookComparator(); + + @BeforeEach + void setUp() { + students = new MyLinkedList<>(); + students.add(new Student("A12", 4.5, 12345)); + students.add(new Student("B32", 3.8, 12346)); + students.add(new Student("Z00", 4.9, 12347)); + students.add(new Student("A12", 4.2, 12348)); + students.add(new Student("B32", 5.0, 12349)); + } + + @Test + void testMergeSortByGroupNumber() { + SortStrategy strategy = new MergeSortStrategy<>(); + strategy.sort(students, groupComparator); + assertOrder(students, "A12", "A12", "B32", "B32", "Z00"); + } + + @Test + void testMergeSortByAverageGrade() { + SortStrategy strategy = new MergeSortStrategy<>(); + strategy.sort(students, gradeComparator); + assertOrder(students, 3.8, 4.2, 4.5, 4.9, 5.0); + } + + @Test + void testMergeSortByRecordBookNumber() { + SortStrategy strategy = new MergeSortStrategy<>(); + strategy.sort(students, recordComparator); + assertOrder(students, 12345, 12346, 12347, 12348, 12349); + } + + @Test + void testBubbleSortByGroupNumber() { + SortStrategy strategy = new BubbleSortStrategy<>(); + strategy.sort(students, groupComparator); + assertOrder(students, "A12", "A12", "B32", "B32", "Z00"); + } + + @Test + void testBubbleSortByAverageGrade() { + SortStrategy strategy = new BubbleSortStrategy<>(); + strategy.sort(students, gradeComparator); + assertOrder(students, 3.8, 4.2, 4.5, 4.9, 5.0); + } + + @Test + void testBubbleSortByRecordBookNumber() { + SortStrategy strategy = new BubbleSortStrategy<>(); + strategy.sort(students, recordComparator); + assertOrder(students, 12345, 12346, 12347, 12348, 12349); + } + + @Test + void testEvenOnlySortByRecordBookNumber() { + MyList list = new MyLinkedList<>(); + list.add(new Student("A01", 4.5, 7)); + list.add(new Student("A02", 4.5, 8)); + list.add(new Student("A03", 4.5, 3)); + list.add(new Student("A04", 4.5, 2)); + list.add(new Student("A05", 4.5, 5)); + list.add(new Student("A06", 4.5, 4)); + + EvenOnlyMergeSortStrategy strategy = + new EvenOnlyMergeSortStrategy<>(Student::getRecordBookNumber); + strategy.sort(list, Comparator.comparingInt(Student::getRecordBookNumber)); + + int[] expected = {7, 2, 3, 4, 5, 8}; + for (int i = 0; i < list.size(); i++) { + assertEquals(expected[i], list.get(i).getRecordBookNumber()); + } + } + + @Test + void testEvenOnlyWithNoEvenElements() { + MyList list = new MyLinkedList<>(); + list.add(new Student("A01", 4.5, 1)); + list.add(new Student("A02", 4.5, 3)); + list.add(new Student("A03", 4.5, 5)); + + EvenOnlyMergeSortStrategy strategy = + new EvenOnlyMergeSortStrategy<>(Student::getRecordBookNumber); + strategy.sort(list, Comparator.comparingInt(Student::getRecordBookNumber)); + + int[] expected = {1, 3, 5}; + for (int i = 0; i < list.size(); i++) { + assertEquals(expected[i], list.get(i).getRecordBookNumber()); + } + } + + @Test + void testEvenOnlyWithAllEvenElements() { + MyList list = new MyLinkedList<>(); + list.add(new Student("A01", 4.5, 4)); + list.add(new Student("A02", 4.5, 2)); + list.add(new Student("A03", 4.5, 6)); + + EvenOnlyMergeSortStrategy strategy = + new EvenOnlyMergeSortStrategy<>(Student::getRecordBookNumber); + strategy.sort(list, Comparator.comparingInt(Student::getRecordBookNumber)); + + int[] expected = {2, 4, 6}; + for (int i = 0; i < list.size(); i++) { + assertEquals(expected[i], list.get(i).getRecordBookNumber()); + } + } + + @Test + void testSortEmptyList() { + MyList empty = new MyLinkedList<>(); + SortStrategy strategy = new MergeSortStrategy<>(); + strategy.sort(empty, groupComparator); + assertEquals(0, empty.size()); + } + + @Test + void testSortSingleElement() { + MyList single = new MyLinkedList<>(); + single.add(new Student("A12", 4.5, 12345)); + SortStrategy strategy = new MergeSortStrategy<>(); + strategy.sort(single, groupComparator); + assertEquals(1, single.size()); + } + + private void assertOrder(MyList list, String... groups) { + assertEquals(groups.length, list.size()); + for (int i = 0; i < groups.length; i++) { + assertEquals(groups[i], list.get(i).getGroupNumber()); + } + } + + private void assertOrder(MyList list, double... grades) { + assertEquals(grades.length, list.size()); + for (int i = 0; i < grades.length; i++) { + assertEquals(grades[i], list.get(i).getAverageGrade(), 0.001); + } + } + + private void assertOrder(MyList list, int... records) { + assertEquals(records.length, list.size()); + for (int i = 0; i < records.length; i++) { + assertEquals(records[i], list.get(i).getRecordBookNumber()); + } + } +} \ No newline at end of file From 62ef9540bfdba4eba2adb5656722173fbe927a8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=8E=D1=89=D0=B8=D0=BA=20=D0=90=D0=BD?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=B0=D1=81=D0=B8=D1=8F?= Date: Fri, 28 Aug 2026 22:54:04 +0300 Subject: [PATCH 24/28] refactor(sorting): reuse merge sort strategy --- .../sorting/EvenOnlyMergeSortStrategy.java | 82 ++----------------- 1 file changed, 7 insertions(+), 75 deletions(-) diff --git a/app/src/main/java/ru/project/sorting/EvenOnlyMergeSortStrategy.java b/app/src/main/java/ru/project/sorting/EvenOnlyMergeSortStrategy.java index a784d7a..45f5b78 100644 --- a/app/src/main/java/ru/project/sorting/EvenOnlyMergeSortStrategy.java +++ b/app/src/main/java/ru/project/sorting/EvenOnlyMergeSortStrategy.java @@ -1,5 +1,6 @@ package ru.project.sorting; +import ru.project.collection.MyLinkedList; import ru.project.collection.MyList; import java.util.Comparator; @@ -7,9 +8,11 @@ import java.util.function.ToIntFunction; public class EvenOnlyMergeSortStrategy implements SortStrategy { private final ToIntFunction valueExtractor; + private final SortStrategy mergeSortStrategy; public EvenOnlyMergeSortStrategy(ToIntFunction valueExtractor) { this.valueExtractor = valueExtractor; + this.mergeSortStrategy = new MergeSortStrategy<>(); } @Override @@ -32,8 +35,7 @@ public class EvenOnlyMergeSortStrategy implements SortStrategy { return; } - @SuppressWarnings("unchecked") - T[] evenElements = (T[]) new Object[evenCount]; + MyList evenElements = new MyLinkedList<>(); int[] evenIndexes = new int[evenCount]; @@ -43,85 +45,15 @@ public class EvenOnlyMergeSortStrategy implements SortStrategy { T element = list.get(i); if (valueExtractor.applyAsInt(element) % 2 == 0) { - evenElements[evenIndex] = element; + evenElements.add(element); evenIndexes[evenIndex] = i; evenIndex++; } } - mergeSort(evenElements, 0, evenElements.length - 1, comparator); + mergeSortStrategy.sort(evenElements, comparator); for (int i = 0; i < evenIndexes.length; i++) { - list.set(evenIndexes[i], evenElements[i]); - } - } - - private void mergeSort( - T[] elements, - int left, - int right, - Comparator comparator - ) { - if (left >= right) { - return; - } - - int mid = (left + right) / 2; - - mergeSort(elements, left, mid, comparator); - mergeSort(elements, mid + 1, right, comparator); - - merge(elements, left, mid, right, comparator); - } - private void merge( - T[] elements, - int left, - int mid, - int right, - Comparator comparator - ) { - int leftSize = mid - left + 1; - int rightSize = right - mid; - - @SuppressWarnings("unchecked") - T[] leftArray = (T[]) new Object[leftSize]; - - @SuppressWarnings("unchecked") - T[] rightArray = (T[]) new Object[rightSize]; - - for (int i = 0; i < leftSize; i++) { - leftArray[i] = elements[left + i]; - } - - for (int j = 0; j < rightSize; j++) { - rightArray[j] = elements[mid + 1 + j]; - } - - int i = 0; - int j = 0; - int k = left; - - while (i < leftSize && j < rightSize) { - if (comparator.compare(leftArray[i], rightArray[j]) <= 0) { - elements[k] = leftArray[i]; - i++; - } else { - elements[k] = rightArray[j]; - j++; - } - - k++; - } - - while (i < leftSize) { - elements[k] = leftArray[i]; - i++; - k++; - } - - while (j < rightSize) { - elements[k] = rightArray[j]; - j++; - k++; + list.set(evenIndexes[i], evenElements.get(i)); } } } From 61280132f1f7948825742564c97b54f091d5fa62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=8E=D1=89=D0=B8=D0=BA=20=D0=90=D0=BD?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=B0=D1=81=D0=B8=D1=8F?= Date: Fri, 28 Aug 2026 22:55:25 +0300 Subject: [PATCH 25/28] test(sorting): add student record book case --- .../EvenOnlyMergeSortStrategyTest.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/app/src/test/java/ru/project/sorting/EvenOnlyMergeSortStrategyTest.java b/app/src/test/java/ru/project/sorting/EvenOnlyMergeSortStrategyTest.java index b423cba..ffaef36 100644 --- a/app/src/test/java/ru/project/sorting/EvenOnlyMergeSortStrategyTest.java +++ b/app/src/test/java/ru/project/sorting/EvenOnlyMergeSortStrategyTest.java @@ -3,6 +3,7 @@ package ru.project.sorting; import org.junit.jupiter.api.Test; import ru.project.collection.MyLinkedList; import ru.project.collection.MyList; +import ru.project.student.Student; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -144,6 +145,33 @@ class EvenOnlyMergeSortStrategyTest { assertEquals(5, list.get(4)); assertEquals(2, list.get(5)); } + + @Test + void shouldUseStudentRecordBookNumberToDetermineEvenElements() { + MyList students = new MyLinkedList<>(); + + students.add(new Student("A01", 4.0, 7)); + students.add(new Student("A02", 4.0, 8)); + students.add(new Student("A03", 4.0, 3)); + students.add(new Student("A04", 4.0, 2)); + students.add(new Student("A05", 4.0, 5)); + students.add(new Student("A06", 4.0, 4)); + + SortStrategy strategy = new EvenOnlyMergeSortStrategy<>( + Student::getRecordBookNumber + ); + + strategy.sort(students, new StudentRecordBookComparator()); + + assertEquals(7, students.get(0).getRecordBookNumber()); + assertEquals(2, students.get(1).getRecordBookNumber()); + assertEquals(3, students.get(2).getRecordBookNumber()); + assertEquals(4, students.get(3).getRecordBookNumber()); + assertEquals(5, students.get(4).getRecordBookNumber()); + assertEquals(8, students.get(5).getRecordBookNumber()); + + assertEquals(6, students.size()); + } } From e02e519b2c630d1cd40e6397d1030774108c71aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=8E=D1=89=D0=B8=D0=BA=20=D0=90=D0=BD?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=B0=D1=81=D0=B8=D1=8F?= Date: Sat, 29 Aug 2026 12:47:02 +0300 Subject: [PATCH 26/28] feat(sorting): add even-only sort strategy --- .../project/sorting/EvenOnlySortStrategy.java | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 app/src/main/java/ru/project/sorting/EvenOnlySortStrategy.java diff --git a/app/src/main/java/ru/project/sorting/EvenOnlySortStrategy.java b/app/src/main/java/ru/project/sorting/EvenOnlySortStrategy.java new file mode 100644 index 0000000..32349c1 --- /dev/null +++ b/app/src/main/java/ru/project/sorting/EvenOnlySortStrategy.java @@ -0,0 +1,94 @@ +package ru.project.sorting; + +import ru.project.collection.MyLinkedList; +import ru.project.collection.MyList; + +import java.util.Comparator; +import java.util.function.ToIntFunction; + +public class EvenOnlySortStrategy implements SortStrategy { + + private SortStrategy sortStrategy; + private ToIntFunction valueExtractor; + + public EvenOnlySortStrategy() { + } + + public EvenOnlySortStrategy(SortStrategy sortStrategy) { + setSortStrategy(sortStrategy); + } + + public EvenOnlySortStrategy( + SortStrategy sortStrategy, + ToIntFunction valueExtractor + ) { + setSortStrategy(sortStrategy); + setValueExtractor(valueExtractor); + } + + public void setSortStrategy(SortStrategy sortStrategy) { + if (sortStrategy == null) { + throw new IllegalArgumentException("Sort strategy must not be null"); + } + + this.sortStrategy = sortStrategy; + } + + public void setValueExtractor(ToIntFunction valueExtractor) { + if (valueExtractor == null) { + throw new IllegalArgumentException("Value extractor must not be null"); + } + + this.valueExtractor = valueExtractor; + } + + @Override + public void sort(MyList list, Comparator comparator) { + if (sortStrategy == null) { + throw new IllegalStateException("Sort strategy is not set"); + } + + if (valueExtractor == null) { + throw new IllegalStateException("Value extractor is not set"); + } + + if (list == null || list.size() <= 1) { + return; + } + + int evenCount = 0; + + for (int i = 0; i < list.size(); i++) { + T element = list.get(i); + + if (valueExtractor.applyAsInt(element) % 2 == 0) { + evenCount++; + } + } + + if (evenCount <= 1) { + return; + } + + MyList evenElements = new MyLinkedList<>(); + int[] evenIndexes = new int[evenCount]; + + int evenIndex = 0; + + for (int i = 0; i < list.size(); i++) { + T element = list.get(i); + + if (valueExtractor.applyAsInt(element) % 2 == 0) { + evenElements.add(element); + evenIndexes[evenIndex] = i; + evenIndex++; + } + } + + sortStrategy.sort(evenElements, comparator); + + for (int i = 0; i < evenIndexes.length; i++) { + list.set(evenIndexes[i], evenElements.get(i)); + } + } +} \ No newline at end of file From 715b411eeadc7009e46ffbd38f90852f3324d91a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D1=80=D1=82=D1=8E=D1=89=D0=B8=D0=BA=20=D0=90=D0=BD?= =?UTF-8?q?=D0=B0=D1=81=D1=82=D0=B0=D1=81=D0=B8=D1=8F?= Date: Sat, 29 Aug 2026 12:47:56 +0300 Subject: [PATCH 27/28] test(sorting): add even-only sort strategy tests --- .../sorting/EvenOnlySortStrategyTest.java | 301 ++++++++++++++++++ 1 file changed, 301 insertions(+) create mode 100644 app/src/test/java/ru/project/sorting/EvenOnlySortStrategyTest.java diff --git a/app/src/test/java/ru/project/sorting/EvenOnlySortStrategyTest.java b/app/src/test/java/ru/project/sorting/EvenOnlySortStrategyTest.java new file mode 100644 index 0000000..8d482bd --- /dev/null +++ b/app/src/test/java/ru/project/sorting/EvenOnlySortStrategyTest.java @@ -0,0 +1,301 @@ +package ru.project.sorting; + +import org.junit.jupiter.api.Test; +import ru.project.collection.MyLinkedList; +import ru.project.collection.MyList; +import ru.project.student.Student; + +import static org.junit.jupiter.api.Assertions.assertSame; + +import java.util.Comparator; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class EvenOnlySortStrategyTest { + + @Test + void shouldHandleEmptyList() { + MyList list = new MyLinkedList<>(); + + EvenOnlySortStrategy strategy = + new EvenOnlySortStrategy<>( + new MergeSortStrategy<>(), + value -> value + ); + + strategy.sort(list, Integer::compare); + + assertEquals(0, list.size()); + } + + @Test + void shouldKeepSingleEvenElementUnchanged() { + MyList list = new MyLinkedList<>(); + list.add(4); + + EvenOnlySortStrategy strategy = + new EvenOnlySortStrategy<>( + new MergeSortStrategy<>(), + value -> value + ); + + strategy.sort(list, Integer::compare); + + assertEquals(4, list.get(0)); + assertEquals(1, list.size()); + } + + @Test + void shouldKeepSingleOddElementUnchanged() { + MyList list = new MyLinkedList<>(); + list.add(7); + + EvenOnlySortStrategy strategy = + new EvenOnlySortStrategy<>( + new MergeSortStrategy<>(), + value -> value + ); + + strategy.sort(list, Integer::compare); + + assertEquals(7, list.get(0)); + assertEquals(1, list.size()); + } + + @Test + void shouldHandleDuplicateEvenValues() { + MyList list = new MyLinkedList<>(); + + list.add(8); + list.add(4); + list.add(8); + list.add(2); + list.add(4); + + EvenOnlySortStrategy strategy = + new EvenOnlySortStrategy<>( + new MergeSortStrategy<>(), + value -> value + ); + + strategy.sort(list, Integer::compare); + + assertEquals(2, list.get(0)); + assertEquals(4, list.get(1)); + assertEquals(4, list.get(2)); + assertEquals(8, list.get(3)); + assertEquals(8, list.get(4)); + } + + @Test + void shouldKeepOddStudentObjectsAtSameIndexes() { + Student oddFirst = new Student("A01", 4.0, 7); + Student evenFirst = new Student("A02", 4.0, 8); + Student oddSecond = new Student("A03", 4.0, 3); + Student evenSecond = new Student("A04", 4.0, 2); + Student oddThird = new Student("A05", 4.0, 5); + Student evenThird = new Student("A06", 4.0, 4); + + MyList students = new MyLinkedList<>(); + + students.add(oddFirst); + students.add(evenFirst); + students.add(oddSecond); + students.add(evenSecond); + students.add(oddThird); + students.add(evenThird); + + EvenOnlySortStrategy strategy = + new EvenOnlySortStrategy<>( + new MergeSortStrategy<>(), + Student::getRecordBookNumber + ); + + strategy.sort(students, new StudentRecordBookComparator()); + + assertSame(oddFirst, students.get(0)); + assertSame(oddSecond, students.get(2)); + assertSame(oddThird, students.get(4)); + + assertEquals(2, students.get(1).getRecordBookNumber()); + assertEquals(4, students.get(3).getRecordBookNumber()); + assertEquals(8, students.get(5).getRecordBookNumber()); + } + + @Test + void shouldSortWhenStrategyPassedThroughConstructor() { + MyList list = new MyLinkedList<>(); + + list.add(8); + list.add(2); + list.add(4); + + EvenOnlySortStrategy strategy = + new EvenOnlySortStrategy<>( + new MergeSortStrategy<>() + ); + + strategy.setValueExtractor(value -> value); + + strategy.sort(list, Integer::compare); + + assertEquals(2, list.get(0)); + assertEquals(4, list.get(1)); + assertEquals(8, list.get(2)); + } + + @Test + void shouldSortOnlyEvenElements() { + MyList students = new MyLinkedList<>(); + + students.add(new Student("A01", 4.0, 7)); + students.add(new Student("A02", 4.0, 8)); + students.add(new Student("A03", 4.0, 3)); + students.add(new Student("A04", 4.0, 2)); + students.add(new Student("A05", 4.0, 5)); + students.add(new Student("A06", 4.0, 4)); + + EvenOnlySortStrategy strategy = new EvenOnlySortStrategy<>(new MergeSortStrategy<>(), Student::getRecordBookNumber); + + strategy.sort(students, new StudentRecordBookComparator()); + + assertEquals(7, students.get(0).getRecordBookNumber()); + assertEquals(2, students.get(1).getRecordBookNumber()); + assertEquals(3, students.get(2).getRecordBookNumber()); + assertEquals(4, students.get(3).getRecordBookNumber()); + assertEquals(5, students.get(4).getRecordBookNumber()); + assertEquals(8, students.get(5).getRecordBookNumber()); + + assertEquals(6, students.size()); + } + + @Test + void shouldSortAllEvenElements() { + MyList list = new MyLinkedList<>(); + + list.add(8); + list.add(2); + list.add(6); + list.add(4); + + EvenOnlySortStrategy strategy = new EvenOnlySortStrategy<>(new MergeSortStrategy<>(), value -> value); + + strategy.sort(list, Integer::compare); + + assertEquals(2, list.get(0)); + assertEquals(4, list.get(1)); + assertEquals(6, list.get(2)); + assertEquals(8, list.get(3)); + } + + @Test + void shouldKeepOddElementsUnchanged() { + MyList list = new MyLinkedList<>(); + + list.add(7); + list.add(3); + list.add(5); + list.add(1); + + EvenOnlySortStrategy strategy = new EvenOnlySortStrategy<>(new MergeSortStrategy<>(), value -> value); + + strategy.sort(list, Integer::compare); + + assertEquals(7, list.get(0)); + assertEquals(3, list.get(1)); + assertEquals(5, list.get(2)); + assertEquals(1, list.get(3)); + } + + @Test + void shouldThrowWhenSortStrategyIsNotSet() { + EvenOnlySortStrategy strategy = new EvenOnlySortStrategy<>(); + + strategy.setValueExtractor(value -> value); + + MyList list = new MyLinkedList<>(); + list.add(2); + list.add(4); + + assertThrows(IllegalStateException.class, () -> strategy.sort(list, Integer::compare)); + } + + @Test + void shouldRejectNullSortStrategy() { + EvenOnlySortStrategy strategy = new EvenOnlySortStrategy<>(); + + assertThrows(IllegalArgumentException.class, () -> strategy.setSortStrategy(null)); + } + + @Test + void shouldDelegateSortingToProvidedStrategy() { + MyList list = new MyLinkedList<>(); + + list.add(7); + list.add(8); + list.add(3); + list.add(2); + + RecordingSortStrategy recordingStrategy = new RecordingSortStrategy(); + + EvenOnlySortStrategy strategy = new EvenOnlySortStrategy<>(recordingStrategy, value -> value); + + strategy.sort(list, Integer::compare); + + assertTrue(recordingStrategy.wasCalled); + assertEquals(2, recordingStrategy.receivedSize); + assertEquals(8, recordingStrategy.firstReceivedElement); + assertEquals(2, recordingStrategy.secondReceivedElement); + } + + @Test + void shouldUseNewStrategyAfterReplacement() { + RecordingSortStrategy firstStrategy = new RecordingSortStrategy(); + + RecordingSortStrategy secondStrategy = new RecordingSortStrategy(); + + EvenOnlySortStrategy strategy = new EvenOnlySortStrategy<>(firstStrategy, value -> value); + + MyList firstList = new MyLinkedList<>(); + firstList.add(4); + firstList.add(2); + + strategy.sort(firstList, Integer::compare); + + assertTrue(firstStrategy.wasCalled); + + strategy.setSortStrategy(secondStrategy); + + MyList secondList = new MyLinkedList<>(); + secondList.add(8); + secondList.add(6); + + strategy.sort(secondList, Integer::compare); + + assertTrue(secondStrategy.wasCalled); + } + + private static class RecordingSortStrategy implements SortStrategy { + + private boolean wasCalled; + private int receivedSize; + private Integer firstReceivedElement; + private Integer secondReceivedElement; + + @Override + public void sort(MyList list, Comparator comparator) { + wasCalled = true; + receivedSize = list.size(); + + if (list.size() > 0) { + firstReceivedElement = list.get(0); + } + + if (list.size() > 1) { + secondReceivedElement = list.get(1); + } + } + } +} \ No newline at end of file From 56652fda719eeb95460aa2c60e175f7ebc6311e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=92=D0=BE=D0=BB=D0=BE=D0=B4=D0=B8=D0=BD=20=D0=93=D0=B5?= =?UTF-8?q?=D1=80=D0=BC=D0=B0=D0=BD?= Date: Sat, 29 Aug 2026 21:21:53 +0400 Subject: [PATCH 28/28] refactor(sorting): remove redundant even-only merge sort strategy --- .../sorting/EvenOnlyMergeSortStrategy.java | 60 ------ .../EvenOnlyMergeSortStrategyTest.java | 177 ------------------ 2 files changed, 237 deletions(-) delete mode 100644 app/src/main/java/ru/project/sorting/EvenOnlyMergeSortStrategy.java delete mode 100644 app/src/test/java/ru/project/sorting/EvenOnlyMergeSortStrategyTest.java diff --git a/app/src/main/java/ru/project/sorting/EvenOnlyMergeSortStrategy.java b/app/src/main/java/ru/project/sorting/EvenOnlyMergeSortStrategy.java deleted file mode 100644 index 45f5b78..0000000 --- a/app/src/main/java/ru/project/sorting/EvenOnlyMergeSortStrategy.java +++ /dev/null @@ -1,60 +0,0 @@ -package ru.project.sorting; - -import ru.project.collection.MyLinkedList; -import ru.project.collection.MyList; - -import java.util.Comparator; -import java.util.function.ToIntFunction; - -public class EvenOnlyMergeSortStrategy implements SortStrategy { - private final ToIntFunction valueExtractor; - private final SortStrategy mergeSortStrategy; - - public EvenOnlyMergeSortStrategy(ToIntFunction valueExtractor) { - this.valueExtractor = valueExtractor; - this.mergeSortStrategy = new MergeSortStrategy<>(); - } - - @Override - public void sort(MyList list, Comparator comparator) { - - if (list == null || list.size() <= 1) { - return; - } - - int evenCount = 0; - - for (int i = 0; i < list.size(); i++) { - T element = list.get(i); - - if (valueExtractor.applyAsInt(element) % 2 == 0) { - evenCount++; - } - } - if (evenCount <= 1) { - return; - } - - MyList evenElements = new MyLinkedList<>(); - - int[] evenIndexes = new int[evenCount]; - - int evenIndex = 0; - - for (int i = 0; i < list.size(); i++) { - T element = list.get(i); - - if (valueExtractor.applyAsInt(element) % 2 == 0) { - evenElements.add(element); - evenIndexes[evenIndex] = i; - evenIndex++; - } - } - mergeSortStrategy.sort(evenElements, comparator); - - for (int i = 0; i < evenIndexes.length; i++) { - list.set(evenIndexes[i], evenElements.get(i)); - } - } -} - diff --git a/app/src/test/java/ru/project/sorting/EvenOnlyMergeSortStrategyTest.java b/app/src/test/java/ru/project/sorting/EvenOnlyMergeSortStrategyTest.java deleted file mode 100644 index ffaef36..0000000 --- a/app/src/test/java/ru/project/sorting/EvenOnlyMergeSortStrategyTest.java +++ /dev/null @@ -1,177 +0,0 @@ -package ru.project.sorting; - -import org.junit.jupiter.api.Test; -import ru.project.collection.MyLinkedList; -import ru.project.collection.MyList; -import ru.project.student.Student; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class EvenOnlyMergeSortStrategyTest { - - @Test - void shouldSortOnlyEvenElements() { - MyList list = new MyLinkedList<>(); - - list.add(7); - list.add(8); - list.add(3); - list.add(2); - list.add(5); - list.add(4); - - EvenOnlyMergeSortStrategy strategy = - new EvenOnlyMergeSortStrategy<>(value -> value); - - strategy.sort(list, Integer::compare); - - assertEquals(7, list.get(0)); - assertEquals(2, list.get(1)); - assertEquals(3, list.get(2)); - assertEquals(4, list.get(3)); - assertEquals(5, list.get(4)); - assertEquals(8, list.get(5)); - - assertEquals(6, list.size()); - } - - @Test - void shouldKeepAllOddElementsUnchanged() { - MyList list = new MyLinkedList<>(); - - list.add(7); - list.add(3); - list.add(5); - list.add(1); - - EvenOnlyMergeSortStrategy strategy = - new EvenOnlyMergeSortStrategy<>(value -> value); - - strategy.sort(list, Integer::compare); - - assertEquals(7, list.get(0)); - assertEquals(3, list.get(1)); - assertEquals(5, list.get(2)); - assertEquals(1, list.get(3)); - } - - @Test - void shouldSortAllEvenElements() { - MyList list = new MyLinkedList<>(); - - list.add(8); - list.add(2); - list.add(6); - list.add(4); - - EvenOnlyMergeSortStrategy strategy = - new EvenOnlyMergeSortStrategy<>(value -> value); - - strategy.sort(list, Integer::compare); - - assertEquals(2, list.get(0)); - assertEquals(4, list.get(1)); - assertEquals(6, list.get(2)); - assertEquals(8, list.get(3)); - } - - @Test - void shouldKeepSingleElementUnchanged() { - MyList list = new MyLinkedList<>(); - - list.add(4); - - EvenOnlyMergeSortStrategy strategy = - new EvenOnlyMergeSortStrategy<>(value -> value); - - strategy.sort(list, Integer::compare); - - assertEquals(4, list.get(0)); - assertEquals(1, list.size()); - } - - @Test - void shouldHandleEmptyList() { - MyList list = new MyLinkedList<>(); - - EvenOnlyMergeSortStrategy strategy = - new EvenOnlyMergeSortStrategy<>(value -> value); - - strategy.sort(list, Integer::compare); - - assertEquals(0, list.size()); - } - - @Test - void shouldUseValueExtractorToDetermineEvenElements() { - MyList list = new MyLinkedList<>(); - - list.add(4); - list.add(3); - list.add(2); - list.add(1); - - EvenOnlyMergeSortStrategy strategy = - new EvenOnlyMergeSortStrategy<>(value -> value + 1); - - strategy.sort(list, Integer::compare); - - assertEquals(4, list.get(0)); - assertEquals(1, list.get(1)); - assertEquals(2, list.get(2)); - assertEquals(3, list.get(3)); - } - - @Test - void shouldUseProvidedComparator() { - MyList list = new MyLinkedList<>(); - - list.add(7); - list.add(2); - list.add(3); - list.add(8); - list.add(5); - list.add(4); - - EvenOnlyMergeSortStrategy strategy = - new EvenOnlyMergeSortStrategy<>(value -> value); - - strategy.sort(list, (first, second) -> Integer.compare(second, first)); - - assertEquals(7, list.get(0)); - assertEquals(8, list.get(1)); - assertEquals(3, list.get(2)); - assertEquals(4, list.get(3)); - assertEquals(5, list.get(4)); - assertEquals(2, list.get(5)); - } - - @Test - void shouldUseStudentRecordBookNumberToDetermineEvenElements() { - MyList students = new MyLinkedList<>(); - - students.add(new Student("A01", 4.0, 7)); - students.add(new Student("A02", 4.0, 8)); - students.add(new Student("A03", 4.0, 3)); - students.add(new Student("A04", 4.0, 2)); - students.add(new Student("A05", 4.0, 5)); - students.add(new Student("A06", 4.0, 4)); - - SortStrategy strategy = new EvenOnlyMergeSortStrategy<>( - Student::getRecordBookNumber - ); - - strategy.sort(students, new StudentRecordBookComparator()); - - assertEquals(7, students.get(0).getRecordBookNumber()); - assertEquals(2, students.get(1).getRecordBookNumber()); - assertEquals(3, students.get(2).getRecordBookNumber()); - assertEquals(4, students.get(3).getRecordBookNumber()); - assertEquals(5, students.get(4).getRecordBookNumber()); - assertEquals(8, students.get(5).getRecordBookNumber()); - - assertEquals(6, students.size()); - } -} - -