Merge pull request into develop from feature/student-search

This commit is contained in:
DELETED
2026-08-31 15:08:11 +04:00
committed by GitHub
10 changed files with 736 additions and 0 deletions
@@ -0,0 +1,125 @@
package ru.project.finder;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class StudentOccurrenceIndexFinder
{
public int[] findOccurrences(MyList<Student> students, Student target) {
if (students == null) {
throw new IllegalArgumentException();
}
if (target == null) {
throw new IllegalArgumentException();
}
if (students.isEmpty()) {
return new int[0];
}
int size = students.size();
int threadCount = calculateThreadCount(size);
int chunkSize = countChunkSize(size, threadCount);
ExecutorService executor = Executors.newFixedThreadPool(threadCount);
MyList<Future<MyList<Integer>>> futures = new MyLinkedList<>();
for (int i = 0; i < threadCount; i++) {
int fromIndex = i * chunkSize;
int toIndex = Math.min(fromIndex + chunkSize, size);
if (fromIndex >= toIndex) {
break;
}
final int start = fromIndex;
final int end = toIndex;
Future<MyList<Integer>> future = executor.submit(() -> {
return findInRange(students, target, start, end);
});
futures.add(future);
}
MyList<Integer> allIndices = new MyLinkedList<>();
try {
for (int i = 0; i < futures.size(); i++) {
Future<MyList<Integer>> future = futures.get(i);
MyList<Integer> partialResult = future.get();
if (partialResult != null) {
for (int j = 0; j < partialResult.size(); j++) {
allIndices.add(partialResult.get(j));
}
}
}
} catch (Exception e) {
throw new RuntimeException("Ошибка при поиске", e);
} finally {
executor.shutdown();
}
sortList(allIndices);
int[] resultArray = new int[allIndices.size()];
for (int i = 0; i < allIndices.size(); i++) {
resultArray[i] = allIndices.get(i);
}
return resultArray;
}
private void sortList(MyList<Integer> list) {
if (list.size() <= 1) return;
MyList<Integer> sorted = new MyLinkedList<>();
for (int i = 0; i < list.size(); i++) {
int value = list.get(i);
int insertIndex = 0;
while (insertIndex < sorted.size()) {
if (sorted.get(insertIndex) > value) {
break;
}
insertIndex++;
}
MyList<Integer> temp = new MyLinkedList<>();
for (int k = 0; k < insertIndex; k++) {
temp.add(sorted.get(k));
}
temp.add(value);
for (int k = insertIndex; k < sorted.size(); k++) {
temp.add(sorted.get(k));
}
sorted = temp;
}
while (!list.isEmpty()) {
list.remove(0);
}
for (int i = 0; i < sorted.size(); i++) {
list.add(sorted.get(i));
}
}
private int calculateThreadCount(int size) {
int processors = Runtime.getRuntime().availableProcessors();
return Math.min(processors, size);
}
private int countChunkSize(int size, int threadCount) {
if (threadCount == 0) return 0;
return (size + threadCount - 1) / threadCount;
}
private MyList<Integer> findInRange(MyList<Student> students, Student target, int fromIndex, int toIndex) {
MyList<Integer> foundIndices = new MyLinkedList<>();
for (int i = fromIndex; i < toIndex; i++) {
Student current = students.get(i);
if (current != null && current.equals(target)) {
foundIndices.add(i);
}
}
return foundIndices;
}
}
@@ -0,0 +1,22 @@
package ru.project.search;
import ru.project.student.Student;
public class AverageGradeRangeCriteria implements StudentSearchCriteria {
private final double min;
private final double max;
public AverageGradeRangeCriteria(double min, double max) {
if (min > max) {
throw new IllegalArgumentException("Min grade must be <= max grade");
}
this.min = min;
this.max = max;
}
@Override
public boolean matches(Student student) {
double grade = student.getAverageGrade();
return grade >= min && grade <= max;
}
}
@@ -0,0 +1,51 @@
package ru.project.search;
import ru.project.student.Student;
import java.util.ArrayList;
import java.util.List;
public class CompositeStudentSearchCriteria implements StudentSearchCriteria {
private final SearchOperation operation;
private final List<StudentSearchCriteria> criteriaList = new ArrayList<>();
public CompositeStudentSearchCriteria(SearchOperation operation) {
if (operation == null) {
throw new IllegalArgumentException("Operation must not be null");
}
this.operation = operation;
}
public void add(StudentSearchCriteria criteria) {
if (criteria == null) {
throw new IllegalArgumentException("Criteria must not be null");
}
criteriaList.add(criteria);
}
public void remove(StudentSearchCriteria criteria) {
criteriaList.remove(criteria);
}
@Override
public boolean matches(Student student) {
if (criteriaList.isEmpty()) {
return operation == SearchOperation.INTERSECTION;
}
if (operation == SearchOperation.UNION) {
for (StudentSearchCriteria c : criteriaList) {
if (c.matches(student)) {
return true;
}
}
return false;
} else {
for (StudentSearchCriteria c : criteriaList) {
if (!c.matches(student)) {
return false;
}
}
return true;
}
}
}
@@ -0,0 +1,25 @@
package ru.project.search;
import ru.project.student.Student;
public class GroupNumberRangeCriteria implements StudentSearchCriteria {
private final String min;
private final String max;
public GroupNumberRangeCriteria(String min, String max) {
if (min == null || max == null) {
throw new IllegalArgumentException("Min and max must not be null");
}
if (min.compareTo(max) > 0) {
throw new IllegalArgumentException("Min group must be <= max group");
}
this.min = min;
this.max = max;
}
@Override
public boolean matches(Student student) {
String group = student.getGroupNumber();
return group.compareTo(min) >= 0 && group.compareTo(max) <= 0;
}
}
@@ -0,0 +1,22 @@
package ru.project.search;
import ru.project.student.Student;
public class RecordBookNumberRangeCriteria implements StudentSearchCriteria {
private final int min;
private final int max;
public RecordBookNumberRangeCriteria(int min, int max) {
if (min > max) {
throw new IllegalArgumentException("Min record number must be <= max");
}
this.min = min;
this.max = max;
}
@Override
public boolean matches(Student student) {
int number = student.getRecordBookNumber();
return number >= min && number <= max;
}
}
@@ -0,0 +1,6 @@
package ru.project.search;
public enum SearchOperation {
UNION,
INTERSECTION
}
@@ -0,0 +1,7 @@
package ru.project.search;
import ru.project.student.Student;
public interface StudentSearchCriteria {
boolean matches(Student student);
}
@@ -0,0 +1,30 @@
package ru.project.search;
import ru.project.list.MyList;
import ru.project.list.MyLinkedList;
import ru.project.student.Student;
public class StudentSearchService {
private final StudentSearchCriteria criteria;
public StudentSearchService(StudentSearchCriteria criteria) {
if (criteria == null) {
throw new IllegalArgumentException("Criteria must not be null");
}
this.criteria = criteria;
}
public MyList<Student> find(MyList<Student> students) {
if (students == null) {
return new MyLinkedList<>();
}
MyList<Student> result = new MyLinkedList<>();
for (int i = 0; i < students.size(); i++) {
Student s = students.get(i);
if (criteria.matches(s)) {
result.add(s);
}
}
return result;
}
}