Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

homework.streams.part2.exercise2 (koshman) #374

Open
wants to merge 6 commits into
base: koshman
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions src/main/java/lambda/data/Employee.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package lambda.data;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class Employee {

private final Person person;
private final List<JobHistoryEntry> jobHistory;

public Employee(Person person, List<JobHistoryEntry> jobHistory) {
this.person = person;
this.jobHistory = new ArrayList<>(jobHistory);
}

public Person getPerson() {
return person;
}

public List<JobHistoryEntry> getJobHistory() {
return new ArrayList<>(jobHistory);
}

@Override
public String toString() {
return "Employee@" + hashCode() + " {"
+ "person=" + person + ", "
+ "jobHistory=" + jobHistory + "}";
}

@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object == null || getClass() != object.getClass()) {
return false;
}
Employee employee = (Employee) object;
return Objects.equals(person, employee.person)
&& Objects.equals(jobHistory, employee.jobHistory);
}

@Override
public int hashCode() {
return Objects.hash(person, jobHistory);
}
}
55 changes: 55 additions & 0 deletions src/main/java/lambda/data/JobHistoryEntry.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package lambda.data;

import java.util.Objects;

public class JobHistoryEntry {

private final String employer;
private final String position;
private final int duration;

public JobHistoryEntry(int duration, String position, String employer) {
this.duration = duration;
this.position = position;
this.employer = employer;
}

public int getDuration() {
return duration;
}

public String getPosition() {
return position;
}

public String getEmployer() {
return employer;
}

@Override
public String toString() {
return "JobHistoryEntry@" + hashCode() + ": {"
+ "duration=" + duration + ", "
+ "position='" + position + "\', "
+ "employer='" + employer + "\'}";
}

@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (other == null || getClass() != other.getClass()) {
return false;
}
JobHistoryEntry entry = (JobHistoryEntry) other;
return duration == entry.duration
&& Objects.equals(position, entry.position)
&& Objects.equals(employer, entry.employer);
}

@Override
public int hashCode() {
return Objects.hash(duration, position, employer);
}
}
15 changes: 10 additions & 5 deletions src/main/java/lambda/data/Person.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package lambda.data;

import org.jetbrains.annotations.NotNull;

import java.io.Serializable;
import java.util.Objects;

public class Person {
public class Person implements Serializable {

private final String firstName;
private final String lastName;
Expand All @@ -14,12 +17,14 @@ public Person(String firstName, String lastName, int age) {
this.age = age;
}

public String getFirstName(Person this) {
return firstName;
public Person() {
firstName = "default";
lastName = "default";
age = -1;
}

public String getLastName() {
return lastName;
public String getLastName(Person this) {
return this.lastName;
}

public int getAge() {
Expand Down
234 changes: 234 additions & 0 deletions src/test/java/streams/part2/exercise/Exercise2.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
package streams.part2.exercise;

import javafx.util.Pair;
import lambda.data.Employee;
import lambda.data.JobHistoryEntry;
import lambda.data.Person;
import org.junit.jupiter.api.Test;

import java.util.*;

import static java.util.stream.Collectors.*;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

@SuppressWarnings("ConstantConditions")
class Exercise2 {

private static List<Employee> getEmployees() {
return Arrays.asList(
new Employee(
new Person("Иван", "Мельников", 30),
Arrays.asList(
new JobHistoryEntry(2, "dev", "EPAM"),
new JobHistoryEntry(1, "dev", "google")
)),
new Employee(
new Person("Александр", "Дементьев", 28),
Arrays.asList(
new JobHistoryEntry(1, "tester", "EPAM"),
new JobHistoryEntry(2, "dev", "EPAM"),
new JobHistoryEntry(2, "dev", "google")
)),
new Employee(
new Person("Дмитрий", "Осинов", 40),
Arrays.asList(
new JobHistoryEntry(3, "QA", "yandex"),
new JobHistoryEntry(1, "QA", "mail.ru"),
new JobHistoryEntry(1, "dev", "mail.ru")
)),
new Employee(
new Person("Анна", "Светличная", 21),
Collections.singletonList(
new JobHistoryEntry(1, "tester", "T-Systems")
)),
new Employee(
new Person("Игорь", "Толмачёв", 50),
Arrays.asList(
new JobHistoryEntry(5, "tester", "EPAM"),
new JobHistoryEntry(6, "QA", "EPAM")
)),
new Employee(
new Person("Иван", "Александров", 33),
Arrays.asList(
new JobHistoryEntry(2, "QA", "T-Systems"),
new JobHistoryEntry(3, "QA", "EPAM"),
new JobHistoryEntry(1, "dev", "EPAM")
))
);
}

private static Map<String, Person> prepareExpected(List<Employee> employees) {
Map<String, Person> expected = new HashMap<>();
expected.put("dev", employees.get(0).getPerson());
expected.put("tester", employees.get(4).getPerson());
expected.put("QA", employees.get(4).getPerson());
return expected;
}

/**
* Преобразовать список сотрудников в отображение [компания -> множество людей, когда-либо работавших в этой компании].
* <p>
* Входные данные:
* [
* {
* {Иван Мельников 30},
* [
* {2, dev, "EPAM"},
* {1, dev, "google"}
* ]
* },
* {
* {Александр Дементьев 28},
* [
* {2, tester, "EPAM"},
* {1, dev, "EPAM"},
* {1, dev, "google"}
* ]
* },
* {
* {Дмитрий Осинов 40},
* [
* {3, QA, "yandex"},
* {1, QA, "EPAM"},
* {1, dev, "mail.ru"}
* ]
* },
* {
* {Анна Светличная 21},
* [
* {1, tester, "T-Systems"}
* ]
* }
* ]
* <p>
* Выходные данные:
* [
* "EPAM" -> [
* {Иван Мельников 30},
* {Александр Дементьев 28},
* {Дмитрий Осинов 40}
* ],
* "google" -> [
* {Иван Мельников 30},
* {Александр Дементьев 28}
* ],
* "yandex" -> [ {Дмитрий Осинов 40} ]
* "mail.ru" -> [ {Дмитрий Осинов 40} ]
* "T-Systems" -> [ {Анна Светличная 21} ]
* ]
*/

@Test
void employersStuffList() {
List<Employee> employees = getEmployees();

Map<String, Set<Person>> result = employees.stream()
.flatMap(employee -> {
Person person = employee.getPerson();
return employee.getJobHistory().stream().map(job -> new Pair<>(job.getEmployer(), person));
})
.collect(groupingBy(Pair::getKey, mapping(Pair::getValue, toSet())));

assertThat(result, hasEntry((is("yandex")), contains(employees.get(2).getPerson())));
assertThat(result, hasEntry((is("mail.ru")), contains(employees.get(2).getPerson())));
assertThat(result, hasEntry((is("google")), containsInAnyOrder(employees.get(0).getPerson(), employees.get(1).getPerson())));
assertThat(result, hasEntry((is("T-Systems")), containsInAnyOrder(employees.get(3).getPerson(), employees.get(5).getPerson())));
assertThat(result, hasEntry((is("EPAM")), containsInAnyOrder(
employees.get(0).getPerson(),
employees.get(1).getPerson(),
employees.get(4).getPerson(),
employees.get(5).getPerson()))
);
}

/**
* Преобразовать список сотрудников в отображение [компания -> множество людей, начавших свою карьеру в этой компании].
* <p>
* Пример.
* <p>
* Входные данные:
* [
* {
* {Иван Мельников 30},
* [
* {2, dev, "EPAM"},
* {1, dev, "google"}
* ]
* },
* {
* {Александр Дементьев 28},
* [
* {2, tester, "EPAM"},
* {1, dev, "EPAM"},
* {1, dev, "google"}
* ]
* },
* {
* {Дмитрий Осинов 40},
* [
* {3, QA, "yandex"},
* {1, QA, "EPAM"},
* {1, dev, "mail.ru"}
* ]
* },
* {
* {Анна Светличная 21},
* [
* {1, tester, "T-Systems"}
* ]
* }
* ]
* <p>
* Выходные данные:
* [
* "EPAM" -> [
* {Иван Мельников 30},
* {Александр Дементьев 28}
* ],
* "yandex" -> [ {Дмитрий Осинов 40} ]
* "T-Systems" -> [ {Анна Светличная 21} ]
* ]
*/

@Test
void indexByFirstEmployer() {
List<Employee> employees = getEmployees();

Map<String, Set<Person>> result = employees.stream()
.map(employee -> new Pair<>(employee.getJobHistory().get(0).getEmployer(), employee.getPerson()))
.collect(groupingBy(Pair::getKey, mapping(Pair::getValue, toSet())));

assertThat(result, hasEntry(is("yandex"), contains(employees.get(2).getPerson())));
assertThat(result, hasEntry(is("T-Systems"), containsInAnyOrder(employees.get(3).getPerson(), employees.get(5).getPerson())));
assertThat(result, hasEntry(is("EPAM"), containsInAnyOrder(
employees.get(0).getPerson(),
employees.get(1).getPerson(),
employees.get(4).getPerson()
)));
}

/**
* Преобразовать список сотрудников в отображение [компания -> сотрудник, суммарно проработавший в ней наибольшее время].
* Гарантируется, что такой сотрудник будет один.
*/
@Test
void greatestExperiencePerEmployer() {
List<Employee> employees = getEmployees();

Map<String, Person> collect = employees.stream()
.flatMap(employee -> {
Person person = employee.getPerson();
return employee.getJobHistory().stream().map(job -> new Pair<>(job, person));
})
.collect(groupingBy(pair -> pair.getKey().getEmployer(),
collectingAndThen(collectingAndThen(toMap(Pair::getValue, x -> x.getKey().getDuration(), (oldValue, newValue) -> oldValue + newValue), entry -> entry.entrySet().stream().max(Comparator.comparing(Map.Entry::getValue))), entry -> entry.get().getKey())));

assertThat(collect, hasEntry("EPAM", employees.get(4).getPerson()));
assertThat(collect, hasEntry("google", employees.get(1).getPerson()));
assertThat(collect, hasEntry("yandex", employees.get(2).getPerson()));
assertThat(collect, hasEntry("mail.ru", employees.get(2).getPerson()));
assertThat(collect, hasEntry("T-Systems", employees.get(5).getPerson()));
}

}