Skip to content

Instantly share code, notes, and snippets.

@tkaczenko
Last active July 29, 2016 12:39
Show Gist options
  • Save tkaczenko/e69a44cf722c639bbcfb146662e430ba to your computer and use it in GitHub Desktop.
Save tkaczenko/e69a44cf722c639bbcfb146662e430ba to your computer and use it in GitHub Desktop.
Simple example of using Stream API and Collections Framework (Java) for demonstration purposes.

Project hierarchy:

src
├── main
│   ├── java
│   │   ├── enumerations
│   │   │   ├── Grade.java
│   │   │   ├── Sex.java
│   │   │   └── Zodiac.java
│   │   ├── models
│   │   │   ├── Card.java
│   │   │   ├── Discipline.java
│   │   │   ├── Student.java
│   │   │   └── Teacher.java
│   │   └── services
│   │       └── StudentsService.java
│   └── resources
└── test
    ├── java
    │   ├── StudentGenerator.java
    │   └── StudentsServiceTest.java
    └── resources
package models;
import enumerations.Grade;
/**
* Model of information about the discipline
*/
public class Card {
/**
* Teacher who teach the discipline
*
* @see Teacher
*/
private Teacher teacher;
/**
* Grade of the discipline
*
* @see Grade
*/
private Grade grade;
private int term;
private int year;
/**
* Constructor for Card with basic information
*
* @param teacher
* @param grade
* @param term
* @param year
*/
public Card(Teacher teacher, Grade grade, int term, int year) {
this.teacher = teacher;
this.grade = grade;
this.term = term;
this.year = year;
}
public Teacher getTeacher() {
return teacher;
}
public void setTeacher(Teacher teacher) {
this.teacher = teacher;
}
public Grade getGrade() {
return grade;
}
public void setGrade(Grade grade) {
this.grade = grade;
}
public int getTerm() {
return term;
}
public void setTerm(int term) {
this.term = term;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
}
package models;
/**
* Model of discipline's data
*/
public class Discipline {
private int id;
private String name;
/**
* Constructor for discipline with basic information
*
* @param id
* @param name
*/
public Discipline(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
package enumerations;
/**
* Enumeration for grade of the discipline
*/
public enum Grade {
A(5) {
@Override
public String gradeEU() {
return "A";
}
},
B(4) {
@Override
public String gradeEU() {
return "B";
}
},
C(3) {
@Override
public String gradeEU() {
return "C";
}
},
D(2) {
@Override
public String gradeEU() {
return "D";
}
},
E(1) {
@Override
public String gradeEU() {
return "E";
}
};
private int value;
public static Grade get(int index) {
switch (index) {
case 1:
return E;
case 2:
return D;
case 3:
return C;
case 4:
return B;
case 5:
return A;
default:
return E;
}
}
Grade(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
/**
* Get Europe name of the grade
*
* @return {@code String} of the grade
*/
public abstract String gradeEU();
}
package enumerations;
/**
* Enumeration for gender
*/
public enum Sex {
MALE {
@Override
public String sex() {
return "male";
}
},
FEMALE {
@Override
public String sex() {
return "female";
}
};
public static Sex get(int index) {
switch (index) {
case 0:
return MALE;
case 1:
return FEMALE;
default:
return MALE;
}
}
/**
* Get name of the gender
*
* @return {@code String} of the gender name
*/
public abstract String sex();
}
package models;
import enumerations.Sex;
import enumerations.Zodiac;
import java.util.Map;
import java.util.function.Predicate;
/**
* Model of student's data
*
* @author Andrii Tkachenko
*/
public class Student {
private String firstName;
private String middleName;
private String lastName;
private short age;
/**
* Zodiac of the student
*
* @see Zodiac
*/
private Zodiac zodiac;
/**
* Gender of the student
*
* @see Sex
*/
private Sex gender;
/**
* Map of discipline and information about this discipline
*
* @see Discipline
* @see Card
*/
private Map<Discipline, Card> disciplineCardMap;
/**
* Check successful student
*
* @param p {@code true} or {@code false} for success
* @return Predicate
* @see Card
*/
public static Predicate<Card> isExcellentGrade(boolean p) {
return p ? card -> card.getGrade().getValue() > 3
: card -> card.getGrade().getValue() < 3;
}
/**
* Constructor for student with basic information
*
* @param firstName
* @param middleName
* @param lastName
* @param age
* @param zodiac
* @param gender
*/
public Student(String firstName, String middleName, String lastName, short age, Zodiac zodiac, Sex gender) {
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
this.age = age;
this.zodiac = zodiac;
this.gender = gender;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public short getAge() {
return age;
}
public void setAge(short age) {
this.age = age;
}
public Zodiac getZodiac() {
return zodiac;
}
public void setZodiac(Zodiac zodiac) {
this.zodiac = zodiac;
}
public Sex getGender() {
return gender;
}
public void setGender(Sex gender) {
this.gender = gender;
}
public Map<Discipline, Card> getDisciplineCardMap() {
return disciplineCardMap;
}
public void setDisciplineCardMap(Map<Discipline, Card> disciplineCardMap) {
this.disciplineCardMap = disciplineCardMap;
}
}
import enumerations.Grade;
import enumerations.Sex;
import enumerations.Zodiac;
import models.Card;
import models.Discipline;
import models.Student;
import models.Teacher;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
/**
* Random generator of students
*
* @author Andrii Tkachenko
* @see Student
*/
public class StudentGenerator {
private long countOfSuccessfulStudent = 0;
private long countOfSuccessfulMen = 0;
/**
* Generate list of students.
* If student is a man then his zodiac will be {@code Zodiac.LEO} else
* his zodiac will be {@code Zodiac.VIRGO}
* If student is unsuccessful then his teacher will be {@code teacherWithDifficultSubjects} else
* he will be randomized
*
* @param sizeOfList
* @param sizeOfMap
* @param teacherWithDifficultSubjects
* @return New {@code List<Student>} of the generated students
*/
public List<Student> generate(long sizeOfList, long sizeOfMap, Teacher teacherWithDifficultSubjects) {
List<Student> students = new ArrayList<>();
Random random = new Random();
boolean flagOfSuccess, flagOfMan;
for (long i = 0; i < sizeOfList; i++) {
Student student;
Map<Discipline, Card> map = new HashMap<>();
flagOfSuccess = random.nextBoolean();
if (flagOfSuccess) {
flagOfMan = random.nextBoolean();
if (flagOfMan) {
student = generateStudent(random, true, true);
countOfSuccessfulMen++;
} else {
student = generateStudent(random, true, false);
}
for (long j = 0; j < sizeOfMap; j++) {
map.put(generateDiscipline(random),
generateCard(random, true, null));
}
countOfSuccessfulStudent++;
} else {
student = generateStudent(random, false, random.nextBoolean());
for (long j = 0; j < sizeOfMap; j++) {
map.put(generateDiscipline(random),
generateCard(random, false, teacherWithDifficultSubjects));
}
}
student.setDisciplineCardMap(map);
students.add(student);
}
return students;
}
/**
* Generate random String in Java using Stream API
*
* @param random {@code java.util.Random}
* @param length Size of the string
* @return Generated new {@code String}
*/
public String generateRandomString(Random random, int length) {
return random.ints(48, 122)
.filter(i -> (i < 57 || i > 65) && (i < 90 || i > 97))
.mapToObj(i -> (char) i)
.limit(length)
.collect(StringBuilder::new, StringBuilder::append, StringBuilder::append)
.toString();
}
/**
* Generate new {@code Student}
*
* @param random {@code java.util.Random}
* @param success If it's {@code true} then the student will be successful else
* he will be randomized
* @param man If it's {@code true} then the student will be a man else
* he will be a woman
* @return Generated new {@code Student}
* @see Student
*/
private Student generateStudent(Random random, boolean success, boolean man) {
if (success) {
return new Student(generateRandomString(random, 5), generateRandomString(random, 5),
generateRandomString(random, 10), (short) random.nextInt(30), man ? Zodiac.get(5) : Zodiac.get(6),
man ? Sex.get(0) : Sex.get(1));
} else {
return new Student(generateRandomString(random, 5), generateRandomString(random, 5),
generateRandomString(random, 10), (short) random.nextInt(30), Zodiac.get(random.nextInt(12)),
Sex.get(random.nextInt(1)));
}
}
/**
* Generate new {@code Student}
*
* @param random {@code java.util.Random}
* @param success If it's {@code true} then the student will be successful else
* he will be unsuccessful
* @param teacher If {@code success} is {@code false} then the student's teacher will be {@code teacher} else
* his teacher will be randomized
* @return Generated new {@code Student}
* @see Card
*/
private Card generateCard(Random random, boolean success, Teacher teacher) {
return new Card(success ? generateTeacher(random) : teacher,
success ? Grade.get(ThreadLocalRandom.current().nextInt(4, 6)) :
Grade.get(ThreadLocalRandom.current().nextInt(1, 4)), random.nextInt(2), random.nextInt(2016));
}
/**
* Generate randomized teacher
*
* @param random {@code java.util.Random}
* @return Generated new {@code Teacher}
* @see Teacher
*/
private Teacher generateTeacher(Random random) {
return new Teacher(generateRandomString(random, 5), generateRandomString(random, 5),
generateRandomString(random, 10));
}
/**
* Generate randomized discipline
*
* @param random {@code java.util.Random}
* @return Generated new {@code Discipline}
* @see Discipline
*/
private Discipline generateDiscipline(Random random) {
return new Discipline(random.nextInt(), generateRandomString(random, 12));
}
public long getCountOfSuccessfulStudent() {
return countOfSuccessfulStudent;
}
public long getCountOfSuccessfulMen() {
return countOfSuccessfulMen;
}
}
package services;
import enumerations.Sex;
import enumerations.Zodiac;
import models.Card;
import models.Discipline;
import models.Student;
import models.Teacher;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
import java.util.stream.Collectors;
/**
* Service of students that do several features using Stream API
*
* @author Andrii Tkachenko
*/
public class StudentsService {
/**
* List of all students
*
* @see Student
*/
private List<Student> students;
/**
* Calculate proportion successful to ordinary students
*
* @return {@code double} proportion of students
*/
public double getProportionSuccessfulToOrdinary() {
long countOfExcellent = students.parallelStream()
.filter(isSuccessfulStudent(true))
.count();
return (double) countOfExcellent / (students.size() - countOfExcellent);
}
/**
* Calculate proportion successful men to women
*
* @return {@code double} proportion of students
*/
public double getProportionSuccessfulMenToWowen() {
long countOfMen = countSuccessfulStudentByGender(Sex.MALE);
long countOfWomen = countSuccessfulStudentByGender(Sex.FEMALE);
return (double) countOfMen / countOfWomen;
}
/**
* Calculate successful zodiac
*
* @return {@code String} of successful zodiac
* @see Zodiac
*/
public String getSuccessfulZodiac() {
Map<Zodiac, Long> map = students.parallelStream()
.filter(isSuccessfulStudent(true))
.collect(Collectors.groupingBy(Student::getZodiac, Collectors.counting()));
return map.entrySet().parallelStream()
.max((e1, e2) -> Long.compare(e1.getValue(), e2.getValue()))
.get().getKey().zodiac();
}
/**
* Calculate the teacher who has got difficult subjects
*
* @return {@code Teacher} who has got difficult subjects
* @see Teacher
*/
public Teacher getTeacherByDifficultSubject() {
Map<Teacher, Long> teachers = new HashMap<>();
for (Student student : students) {
for (Map.Entry<Discipline, Card> entry : student.getDisciplineCardMap().entrySet()) {
if (entry.getValue().getGrade().getValue() < 3) {
Teacher temp = entry.getValue().getTeacher();
if (teachers.containsKey(temp)) {
teachers.put(temp, teachers.get(temp) + 1);
} else {
teachers.put(temp, 1L);
}
}
}
}
return teachers.entrySet().parallelStream()
.max((e1, e2) -> Long.compare(e1.getValue(), e2.getValue()))
.get().getKey();
}
/**
* Calculate successful students by gender
*
* @param sex If it's {@code true} then calculate successful men else
* successful women
* @return Number of all successful students
* @see Sex
*/
private long countSuccessfulStudentByGender(Sex sex) {
return students.parallelStream()
.filter(isSuccessfulStudent(true))
.filter(student -> student.getGender() == sex)
.count();
}
/**
* Check successful student
*
* @param p true or false for success
* @return Predicate
* @see Card
*/
private Predicate<Student> isSuccessfulStudent(boolean p) {
return student -> {
Collection<Card> t = student.getDisciplineCardMap().values();
return t.size() == t.parallelStream()
.filter(student.isExcellentGrade(p))
.count();
};
}
public void setStudents(List<Student> students) {
this.students = students;
}
}
import enumerations.Zodiac;
import models.Student;
import models.Teacher;
import org.junit.Before;
import org.junit.Test;
import services.StudentsService;
import java.util.List;
import java.util.Random;
import static org.junit.Assert.assertEquals;
/**
* Created by tkacz- on 14.07.16.
*
* @author Andrii Tkachenko
* @see StudentsService
*/
public class StudentsServiceTest {
private final double DELTA = 1E-3;
/**
* Mock object for StudentsService
*
* @see StudentsService
*/
private StudentsService service;
/**
* Random generator of students, teachers,
* card and etc.
*
* @see StudentGenerator
*/
private StudentGenerator generator;
private List<Student> students;
private Teacher teacher;
/**
* Set up the all objects for checking StudentsService
*
* @throws Exception
*/
@Before
public void setUp() throws Exception {
Random random = new Random();
service = new StudentsService();
generator = new StudentGenerator();
teacher = new Teacher(generator.generateRandomString(random, 10),
generator.generateRandomString(random, 10), generator.generateRandomString(random, 15));
students = generator.generate(100, 11, teacher);
service.setStudents(students);
}
/**
* When list exists, propotion successful to ordinary students
* should be equal expected result
*
* @throws Exception
* @result The proportion equals expected result
* @see StudentsService#getProportionSuccessfulToOrdinary()
*/
@Test
public void whenListExistsProportionSuccessfulToOrdinaryShouldBeEqualToExpectedResult() throws Exception {
long countOfSuccessfulStudent = generator.getCountOfSuccessfulStudent();
double expected = (double) countOfSuccessfulStudent / (students.size() - countOfSuccessfulStudent);
double actual = service.getProportionSuccessfulToOrdinary();
assertEquals(expected, actual, DELTA);
}
/**
* When list exists, proportion successful mans to successful women
* should be equal expected result
*
* @throws Exception
* @result The proportion equals expected result
* @see StudentsService#getProportionSuccessfulMenToWowen()
*/
@Test
public void whenListExistsProportionSuccessfulMenToWowenShouldBeEqualExpectedResult() throws Exception {
long countOfSuccessfulStudent = generator.getCountOfSuccessfulStudent();
long countOfSuccessfulMen = generator.getCountOfSuccessfulMen();
double expected = (double) countOfSuccessfulMen / (countOfSuccessfulStudent - countOfSuccessfulMen);
double actual = service.getProportionSuccessfulMenToWowen();
assertEquals(expected, actual, DELTA);
}
/**
* When list exists successful zodiac
* should be equal expected result
*
* @throws Exception
* @result Successful zodiac equals expected result
* @see StudentsService#getSuccessfulZodiac()
*/
@Test
public void whenListExistsSuccessfulZodiacShouldBeEqualExpectedResult() throws Exception {
long countOfSuccessfulStudent = generator.getCountOfSuccessfulStudent();
long countOfSuccessfulMen = generator.getCountOfSuccessfulMen();
String expected = (countOfSuccessfulMen >
(countOfSuccessfulStudent - countOfSuccessfulMen)) ? Zodiac.LEO.zodiac() : Zodiac.VIRGO.zodiac();
String actual = service.getSuccessfulZodiac();
assertEquals(expected, actual);
}
/**
* When list exists teacher who has got difficult subjects
* should be equal expected result
*
* @throws Exception
* @result Teacher's full name equals expected result
* @see StudentsService#getTeacherByDifficultSubject()
*/
@Test
public void whenListExistsTeacherWithDifficultSubjectShouldBeEqualExpectedResult() throws Exception {
Teacher actual = service.getTeacherByDifficultSubject();
assertEquals(teacher.getFirstName(), actual.getFirstName());
assertEquals(teacher.getMiddleName(), actual.getMiddleName());
assertEquals(teacher.getLastName(), actual.getLastName());
}
}
package models;
import java.util.List;
/**
* Model of teacher's data
*/
public class Teacher {
private String firstName;
private String middleName;
private String lastName;
/**
* List of the teacher's disciplines
*
* @see Discipline
*/
private List<Discipline> disciplines;
/**
* Constructor for Teacher with basic information
*
* @param firstName
* @param middleName
* @param lastName
*/
public Teacher(String firstName, String middleName, String lastName) {
this.firstName = firstName;
this.middleName = middleName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getMiddleName() {
return middleName;
}
public void setMiddleName(String middleName) {
this.middleName = middleName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public List<Discipline> getDisciplines() {
return disciplines;
}
public void setDisciplines(List<Discipline> disciplines) {
this.disciplines = disciplines;
}
}
package enumerations;
/**
* Enumeration for zodiac
*/
public enum Zodiac {
ARIES(1) {
@Override
public String zodiac() {
return "Aries";
}
},
TAURUS(2) {
@Override
public String zodiac() {
return "Taurus";
}
},
GEMINI(3) {
@Override
public String zodiac() {
return "Gemini";
}
},
CANCER(4) {
@Override
public String zodiac() {
return "Cancer";
}
},
LEO(5) {
@Override
public String zodiac() {
return "Leo";
}
},
VIRGO(6) {
@Override
public String zodiac() {
return "Virgio";
}
},
LIBRA(7) {
@Override
public String zodiac() {
return "Libra";
}
},
SCORPIO(8) {
@Override
public String zodiac() {
return "Scorpio";
}
},
SAGGITTARIUS(9) {
@Override
public String zodiac() {
return "Saggittarius";
}
},
CAPRICORN(10) {
@Override
public String zodiac() {
return "Capricorn";
}
},
AQUARIUS(11) {
@Override
public String zodiac() {
return "Aquarius";
}
},
PISCES(12) {
@Override
public String zodiac() {
return "Pisces";
}
};
private int value;
public static Zodiac get(int index) {
switch (index) {
case 1:
return ARIES;
case 2:
return TAURUS;
case 3:
return GEMINI;
case 4:
return CANCER;
case 5:
return LEO;
case 6:
return VIRGO;
case 7:
return LIBRA;
case 8:
return SCORPIO;
case 9:
return SAGGITTARIUS;
case 10:
return CAPRICORN;
case 11:
return AQUARIUS;
case 12:
return PISCES;
default:
return ARIES;
}
}
Zodiac(int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
/**
* Get name of the zodiac
*
* @return {@code String} of the zodiac name
*/
public abstract String zodiac();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment