feat(random): generate students using streams

- generate students with IntStream
- collect generated students into MyList using MyListCollector
- round average grade to two decimal places
- extract student generation into a separate method
This commit is contained in:
2026-09-01 23:35:52 +04:00
parent 7d1e36917d
commit 6e7040b245
@@ -1,53 +1,63 @@
package ru.project.random; package ru.project.random;
import ru.project.collection.MyLinkedList;
import ru.project.collection.MyList;
import ru.project.student.Student;
import java.util.Random; import java.util.Random;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import java.util.stream.IntStream;
import ru.project.collection.MyList;
import ru.project.collectors.MyCollectors;
import ru.project.student.Student;
import ru.project.student.StudentBuilder; import ru.project.student.StudentBuilder;
public class RandomStudentGenerator
{ public class RandomStudentGenerator {
private static final Random RANDOM = new Random(); private static final Random RANDOM = new Random();
private String minGroupNumber; private String minGroupNumber;
private String maxGroupNumber; private String maxGroupNumber;
private Double minAverageGrade; private Double minAverageGrade;
private Double maxAverageGrade; private Double maxAverageGrade;
private Integer minRecordBookNumber; private Integer minRecordBookNumber;
private Integer maxRecordBookNumber; private Integer maxRecordBookNumber;
private static final double DEFAULT_MIN_GRADE = 0.0; private static final double DEFAULT_MIN_GRADE = 0.0;
private static final double DEFAULT_MAX_GRADE = 5.0; private static final double DEFAULT_MAX_GRADE = 5.0;
private static final int DEFAULT_MIN_RECORD_BOOK = 1; private static final int DEFAULT_MIN_RECORD_BOOK = 1;
private static final String GROUP_PATTERN_REGEX = "^[A-Z][0-9]{2}$"; private static final String GROUP_PATTERN_REGEX = "^[A-Z][0-9]{2}$";
private static final Pattern GROUP_PATTERN = Pattern.compile(GROUP_PATTERN_REGEX); private static final Pattern GROUP_PATTERN = Pattern.compile(GROUP_PATTERN_REGEX);
public RandomStudentGenerator setMinGroupNumber(String minGroupNumber) { public RandomStudentGenerator setMinGroupNumber(String minGroupNumber) {
if (minGroupNumber != null && !GROUP_PATTERN.matcher(minGroupNumber).matches()) { if (minGroupNumber != null && !GROUP_PATTERN.matcher(minGroupNumber).matches()) {
throw new IllegalArgumentException("minGroupNumber does not match Student group pattern: " + GROUP_PATTERN_REGEX);
} throw new IllegalArgumentException(
this.minGroupNumber = minGroupNumber; "minGroupNumber does not match Student group pattern: " + GROUP_PATTERN_REGEX);
return this;
}
public RandomStudentGenerator setMaxGroupNumber(String maxGroupNumber) {
if (maxGroupNumber != null && !GROUP_PATTERN.matcher(maxGroupNumber).matches()) {
throw new IllegalArgumentException("maxGroupNumber does not match Student group pattern: " + GROUP_PATTERN_REGEX);
}
this.maxGroupNumber = maxGroupNumber;
return this;
} }
this.minGroupNumber = minGroupNumber; this.minGroupNumber = minGroupNumber;
return this; return this;
} }
public RandomStudentGenerator setMaxGroupNumber(String maxGroupNumber) { public RandomStudentGenerator setMaxGroupNumber(String maxGroupNumber) {
if (maxGroupNumber != null && !GROUP_PATTERN.matcher(maxGroupNumber).matches()) { if (maxGroupNumber != null && !GROUP_PATTERN.matcher(maxGroupNumber).matches()) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"maxGroupNumber does not match Student group pattern: " + GROUP_PATTERN_REGEX); "maxGroupNumber does not match Student group pattern: " + GROUP_PATTERN_REGEX);
} }
this.maxGroupNumber = maxGroupNumber; this.maxGroupNumber = maxGroupNumber;
return this; return this;
} }
public RandomStudentGenerator setMinAverageGrade(double minAverageGrade) { public RandomStudentGenerator setMinAverageGrade(double minAverageGrade) {
if (minAverageGrade < DEFAULT_MIN_GRADE || minAverageGrade > DEFAULT_MAX_GRADE) { if (minAverageGrade < DEFAULT_MIN_GRADE || minAverageGrade > DEFAULT_MAX_GRADE) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"minAverageGrade out of Student allowed range [" "minAverageGrade out of Student allowed range ["
+ DEFAULT_MIN_GRADE + DEFAULT_MIN_GRADE
@@ -55,12 +65,16 @@ public class RandomStudentGenerator
+ DEFAULT_MAX_GRADE + DEFAULT_MAX_GRADE
+ "]"); + "]");
} }
this.minAverageGrade = minAverageGrade; this.minAverageGrade = minAverageGrade;
return this; return this;
} }
public RandomStudentGenerator setMaxAverageGrade(double maxAverageGrade) { public RandomStudentGenerator setMaxAverageGrade(double maxAverageGrade) {
if (maxAverageGrade < DEFAULT_MIN_GRADE || maxAverageGrade > DEFAULT_MAX_GRADE) { if (maxAverageGrade < DEFAULT_MIN_GRADE || maxAverageGrade > DEFAULT_MAX_GRADE) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"maxAverageGrade out of Student allowed range [" "maxAverageGrade out of Student allowed range ["
+ DEFAULT_MIN_GRADE + DEFAULT_MIN_GRADE
@@ -68,25 +82,33 @@ public class RandomStudentGenerator
+ DEFAULT_MAX_GRADE + DEFAULT_MAX_GRADE
+ "]"); + "]");
} }
this.maxAverageGrade = maxAverageGrade; this.maxAverageGrade = maxAverageGrade;
return this; return this;
} }
public RandomStudentGenerator setMinRecordBookNumber(int minRecordBookNumber) { public RandomStudentGenerator setMinRecordBookNumber(int minRecordBookNumber) {
if (minRecordBookNumber < DEFAULT_MIN_RECORD_BOOK) { if (minRecordBookNumber < DEFAULT_MIN_RECORD_BOOK) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"minRecordBookNumber must be >= " + DEFAULT_MIN_RECORD_BOOK); "minRecordBookNumber must be >= " + DEFAULT_MIN_RECORD_BOOK);
} }
this.minRecordBookNumber = minRecordBookNumber; this.minRecordBookNumber = minRecordBookNumber;
return this; return this;
} }
public RandomStudentGenerator setMaxRecordBookNumber(int maxRecordBookNumber) { public RandomStudentGenerator setMaxRecordBookNumber(int maxRecordBookNumber) {
if (maxRecordBookNumber < DEFAULT_MIN_RECORD_BOOK) { if (maxRecordBookNumber < DEFAULT_MIN_RECORD_BOOK) {
throw new IllegalArgumentException( throw new IllegalArgumentException(
"maxRecordBookNumber must be >= " + DEFAULT_MIN_RECORD_BOOK); "maxRecordBookNumber must be >= " + DEFAULT_MIN_RECORD_BOOK);
} }
this.maxRecordBookNumber = maxRecordBookNumber; this.maxRecordBookNumber = maxRecordBookNumber;
return this; return this;
} }
@@ -94,75 +116,116 @@ public class RandomStudentGenerator
if (size < 0) { if (size < 0) {
throw new IllegalArgumentException("size must be non-negative"); throw new IllegalArgumentException("size must be non-negative");
} }
validateRanges(); validateRanges();
MyList<Student> result = new MyLinkedList<>();
for (int i = 0; i < size; i++) {
String group = generateGroupNumber();
double grade = generateAverageGrade();
int recordBook = generateRecordBookNumber();
Student student = return IntStream.range(0, size)
new StudentBuilder() .mapToObj(i -> generateStudent())
.setGroupNumber(group) .collect(MyCollectors.toMyList());
.setAverageGrade(grade) }
.setRecordBookNumber(recordBook)
private Student generateStudent() {
String groupNumber = generateGroupNumber();
double averageGrade = generateAverageGrade();
int recordBookNumber = generateRecordBookNumber();
return new StudentBuilder()
.setGroupNumber(groupNumber)
.setAverageGrade(averageGrade)
.setRecordBookNumber(recordBookNumber)
.build(); .build();
result.add(student);
}
return result;
} }
private double generateAverageGrade() { private void validateRanges() {
double min = (minAverageGrade != null) ? minAverageGrade : DEFAULT_MIN_GRADE; double effectiveMinGrade = minAverageGrade != null ? minAverageGrade : DEFAULT_MIN_GRADE;
double max = (maxAverageGrade != null) ? maxAverageGrade : DEFAULT_MAX_GRADE;
double range = max - min; double effectiveMaxGrade = maxAverageGrade != null ? maxAverageGrade : DEFAULT_MAX_GRADE;
double grade = min + (range * RANDOM.nextDouble());
return Math.round(grade * 100.0) / 100.0; if (effectiveMinGrade > effectiveMaxGrade) {
throw new IllegalArgumentException("minAverageGrade cannot be greater than maxAverageGrade");
} }
if (minGroupNumber != null && maxGroupNumber != null) {
if (minGroupNumber.compareTo(maxGroupNumber) > 0) { int effectiveMinRecord =
minRecordBookNumber != null ? minRecordBookNumber : DEFAULT_MIN_RECORD_BOOK;
int effectiveMaxRecord = maxRecordBookNumber != null ? maxRecordBookNumber : Integer.MAX_VALUE;
if (effectiveMaxRecord == Integer.MAX_VALUE) {
effectiveMaxRecord = effectiveMinRecord + 999_999;
}
if (effectiveMinRecord > effectiveMaxRecord) {
throw new IllegalArgumentException(
"minRecordBookNumber cannot be greater than maxRecordBookNumber");
}
if (minGroupNumber != null
&& maxGroupNumber != null
&& minGroupNumber.compareTo(maxGroupNumber) > 0) {
throw new IllegalArgumentException("minGroupNumber cannot be greater than maxGroupNumber"); throw new IllegalArgumentException("minGroupNumber cannot be greater than maxGroupNumber");
} }
} }
}
private String generateGroupNumber() { private String generateGroupNumber() {
String min = (minGroupNumber != null) ? minGroupNumber : "A00"; String min = minGroupNumber != null ? minGroupNumber : "A00";
String max = (maxGroupNumber != null) ? maxGroupNumber : "Z99";
String max = maxGroupNumber != null ? maxGroupNumber : "Z99";
char minLetter = min.charAt(0); char minLetter = min.charAt(0);
char maxLetter = max.charAt(0); char maxLetter = max.charAt(0);
int minDigit = Integer.parseInt(min.substring(1)); int minDigit = Integer.parseInt(min.substring(1));
int maxDigit = Integer.parseInt(max.substring(1)); int maxDigit = Integer.parseInt(max.substring(1));
char letter = (char) (minLetter + RANDOM.nextInt((maxLetter - minLetter) + 1)); char letter = (char) (minLetter + RANDOM.nextInt((maxLetter - minLetter) + 1));
int digit; int digit;
if (letter == minLetter && letter == maxLetter) { if (letter == minLetter && letter == maxLetter) {
digit = minDigit + RANDOM.nextInt((maxDigit - minDigit) + 1); digit = minDigit + RANDOM.nextInt((maxDigit - minDigit) + 1);
} else if (letter == minLetter) { } else if (letter == minLetter) {
digit = minDigit + RANDOM.nextInt(100 - minDigit); digit = minDigit + RANDOM.nextInt(100 - minDigit);
} else if (letter == maxLetter) { } else if (letter == maxLetter) {
digit = RANDOM.nextInt(maxDigit + 1); digit = RANDOM.nextInt(maxDigit + 1);
} else { } else {
digit = RANDOM.nextInt(100); digit = RANDOM.nextInt(100);
} }
return letter + String.format("%02d", digit); return letter + String.format("%02d", digit);
} }
private double generateAverageGrade() { private double generateAverageGrade() {
double min = (minAverageGrade != null) ? minAverageGrade : DEFAULT_MIN_GRADE; double min = minAverageGrade != null ? minAverageGrade : DEFAULT_MIN_GRADE;
double max = (maxAverageGrade != null) ? maxAverageGrade : DEFAULT_MAX_GRADE;
double max = maxAverageGrade != null ? maxAverageGrade : DEFAULT_MAX_GRADE;
double range = max - min; double range = max - min;
return min + (range * RANDOM.nextDouble());
double grade = min + (range * RANDOM.nextDouble());
return Math.round(grade * 100.0) / 100.0;
} }
private int generateRecordBookNumber() { private int generateRecordBookNumber() {
int min = (minRecordBookNumber != null) ? minRecordBookNumber : DEFAULT_MIN_RECORD_BOOK; int min = minRecordBookNumber != null ? minRecordBookNumber : DEFAULT_MIN_RECORD_BOOK;
int max =
(maxRecordBookNumber != null) ? maxRecordBookNumber : min + 999_999; // разумный максимум int max = maxRecordBookNumber != null ? maxRecordBookNumber : min + 999_999;
if (max < min) { if (max < min) {
max = min; max = min;
} }
return min + RANDOM.nextInt((max - min) + 1); return min + RANDOM.nextInt((max - min) + 1);
} }
} }