diff --git a/src/main/java/data/Generator.java b/src/main/java/data/Generator.java index cbd46ea..1ed0dc5 100644 --- a/src/main/java/data/Generator.java +++ b/src/main/java/data/Generator.java @@ -60,7 +60,8 @@ public static Employee generateEmployee() { } public static List generateEmployeeList() { - // TODO - throw new UnsupportedOperationException(); + return Stream.generate(Generator::generateEmployee) + .limit(10) + .collect(toList()); } } diff --git a/src/test/java/part1/exercise/StreamsExercise1.java b/src/test/java/part1/exercise/StreamsExercise1.java index 02dd2da..4bf509c 100755 --- a/src/test/java/part1/exercise/StreamsExercise1.java +++ b/src/test/java/part1/exercise/StreamsExercise1.java @@ -1,6 +1,7 @@ package part1.exercise; import data.Employee; +import data.Generator; import data.JobHistoryEntry; import data.Person; import org.junit.Test; @@ -15,6 +16,9 @@ import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.mapping; import static java.util.stream.Collectors.toList; +import static org.junit.Assert.assertEquals; + +import javax.naming.ldap.LdapName; public class StreamsExercise1 { // https://youtu.be/kxgo7Y4cdA8 Сергей Куксенко и Алексей Шипилёв — Через тернии к лямбдам, часть 1 @@ -25,16 +29,49 @@ public class StreamsExercise1 { @Test public void getAllEpamEmployees() { - List epamEmployees = null;// TODO all persons with experience in epam - throw new UnsupportedOperationException(); + // TODO all persons with experience in epam + final List employeeList = Generator.generateEmployeeList(); + + List actualPersonList = employeeList.stream() + .filter(employee -> employee.getJobHistory().stream() + .map(JobHistoryEntry::getEmployer) + .anyMatch("epam"::equalsIgnoreCase) + ) + .map(Employee::getPerson) + .collect(toList()); + + List expectedPersonList = new ArrayList<>(); + for (Employee employee : employeeList) { + for (JobHistoryEntry historyEntry : employee.getJobHistory()) { + if (historyEntry.getEmployer().equalsIgnoreCase("epam")) { + expectedPersonList.add(employee.getPerson()); + break; + } + } + } + assertEquals(actualPersonList.size(), expectedPersonList.size()); } @Test public void getEmployeesStartedFromEpam() { - List epamEmployees = null;// TODO all persons with first experience in epam - throw new UnsupportedOperationException(); + // TODO all persons with first experience in epam + final List employeeList = Generator.generateEmployeeList(); + List epamEmployees = employeeList.stream() + .filter(e -> e.getJobHistory().stream().limit(1).collect(toList()).get(0).getEmployer().equals("epam")) + .map(Employee::getPerson) + .collect(Collectors.toList()); + List expectedList = new ArrayList<>(); + + for (Employee anEmployeeList : employeeList) { + if (anEmployeeList.getJobHistory().get(0).getEmployer().equalsIgnoreCase("epam")) { + + expectedList.add(anEmployeeList.getPerson()); + } + } + assertEquals(expectedList, epamEmployees); } + @Test public void sumEpamDurations() { final List employees = generateEmployeeList(); @@ -49,11 +86,12 @@ public void sumEpamDurations() { } } - // TODO - throw new UnsupportedOperationException(); - - // int result = ??? - // assertEquals(expected, result); + final int result = employees.stream() + .flatMap(employee -> employee.getJobHistory().stream()) + .filter(j -> j.getEmployer().equals("epam")) + .mapToInt(JobHistoryEntry::getDuration) + .sum(); + assertEquals(expected, result); } } diff --git a/src/test/java/part1/exercise/StreamsExercise2.java b/src/test/java/part1/exercise/StreamsExercise2.java index 5be9d38..3144e27 100755 --- a/src/test/java/part1/exercise/StreamsExercise2.java +++ b/src/test/java/part1/exercise/StreamsExercise2.java @@ -5,119 +5,233 @@ import data.Person; import org.junit.Test; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import java.util.stream.Stream; import static data.Generator.generateEmployeeList; +import static java.util.Comparator.comparing; import static java.util.stream.Collectors.*; import static org.junit.Assert.assertEquals; -public class StreamsExercise2 { - // https://youtu.be/kxgo7Y4cdA8 Сергей Куксенко и Алексей Шипилёв — Через тернии к лямбдам, часть 1 +public class StreamsExercise2 {// https://youtu.be/kxgo7Y4cdA8 Сергей Куксенко и Алексей Шипилёв — Через тернии к лямбдам, часть 1 // https://youtu.be/JRBWBJ6S4aU Сергей Куксенко и Алексей Шипилёв — Через тернии к лямбдам, часть 2 // https://youtu.be/O8oN4KSZEXE Сергей Куксенко — Stream API, часть 1 // https://youtu.be/i0Jr2l3jrDA Сергей Куксенко — Stream API, часть 2 - // TODO class PersonEmployerPair + private static class PersonEmployerPair { + + private final Person person; + private final String employer; + + public PersonEmployerPair(Person person, String employer) { + this.person = person; + this.employer = employer; + } + + public Person getPerson() { + return person; + } + + public String getEmployer() { + return employer; + } + } + + private static Stream employeeToPairs(Employee employee) { + return employee.getJobHistory().stream() + .map(JobHistoryEntry::getEmployer) + .map(e -> new PersonEmployerPair(employee.getPerson(), e)); + } @Test public void employersStuffLists() { - Map> employersStuffLists = null;// TODO - throw new UnsupportedOperationException(); + + final Stream personEmployerPairStream = getEmployees().stream() + .flatMap(StreamsExercise2::employeeToPairs); + + Map> employersStuffLists = personEmployerPairStream + .collect( + HashMap::new, + (m, p) -> { + final List list = m.computeIfAbsent(p.getEmployer(), (k) -> new ArrayList<>()); + list.add(p.getPerson()); + }, + (m1, m2) -> { + for (Map.Entry> entry : m2.entrySet()) { + List list = m1.computeIfAbsent(entry.getKey(), + (k) -> new ArrayList<>()); + list.addAll(entry.getValue()); + } + } + ); + + final Map> expectedList = personEmployerPairStream.collect( + Collectors.groupingBy + (PersonEmployerPair::getEmployer, + Collectors.mapping(PersonEmployerPair::getPerson, Collectors.toList()))); + + assertEquals(employersStuffLists, expectedList); + } + + private static PersonEmployerPair firstEmployerPersonPair(Employee employee) { + final JobHistoryEntry jobHistoryEntry = employee.getJobHistory().stream() + .findFirst() + .get(); + + return new PersonEmployerPair(employee.getPerson(), jobHistoryEntry.getEmployer()); } @Test public void indexByFirstEmployer() { - Map> employeesIndex = null;// TODO - throw new UnsupportedOperationException(); + Map> employeesIndex = new HashMap<>(); + final List employees = getEmployees(); + for (Employee employee : employees) { + for (JobHistoryEntry jobHistoryEntry : employee.getJobHistory()) { + employeesIndex.put(jobHistoryEntry.getEmployer(), new ArrayList<>()); + } + } + for (Employee employee : employees) { + employeesIndex.get(employee.getJobHistory().get(0).getEmployer()).add(employee.getPerson()); + } + + employeesIndex.entrySet().removeIf(entry -> entry.getValue().equals(Collections.EMPTY_LIST)); + + final Stream personEmployerPairStream = employees.stream() + .map(StreamsExercise2::firstEmployerPersonPair); + + final Map> expected = personEmployerPairStream + .collect(Collectors.groupingBy + (PersonEmployerPair::getEmployer, + Collectors.mapping(PersonEmployerPair::getPerson, Collectors.toList()))); + + assertEquals(employeesIndex, expected); + } + + private static class PersonEmployerDuration { + + private final Person person; + private final String employer; + private final int duration; + + public PersonEmployerDuration(Person person, String employer, int duration) { + this.person = person; + this.employer = employer; + this.duration = duration; + } + + public Person getPerson() { + return person; + } + + public String getEmployer() { + return employer; + } + + public int getDuration() { + return duration; + } } @Test public void greatestExperiencePerEmployer() { - Map employeesIndex = null;// TODO + Map employeesIndex = null; + final List employees = getEmployees(); + final Stream personEmployerDurationStream = employees.stream() + .flatMap( + e -> e.getJobHistory() + .stream() + .map(j -> new PersonEmployerDuration(e.getPerson(), j.getEmployer(), j.getDuration()))); + + employeesIndex = personEmployerDurationStream + .collect(groupingBy( + PersonEmployerDuration::getEmployer, + collectingAndThen( + maxBy(comparing(PersonEmployerDuration::getDuration)), p -> p.get().getPerson()))); assertEquals(new Person("John", "White", 28), employeesIndex.get("epam")); } - private List getEmployees() { return Arrays.asList( - new Employee( - new Person("John", "Galt", 20), - Arrays.asList( - new JobHistoryEntry(3, "dev", "epam"), - new JobHistoryEntry(2, "dev", "google") - )), - new Employee( - new Person("John", "Doe", 21), - Arrays.asList( - new JobHistoryEntry(4, "BA", "yandex"), - new JobHistoryEntry(2, "QA", "epam"), - new JobHistoryEntry(2, "dev", "abc") - )), - new Employee( - new Person("John", "White", 22), - Collections.singletonList( - new JobHistoryEntry(6, "QA", "epam") - )), - new Employee( - new Person("John", "Galt", 23), - Arrays.asList( - new JobHistoryEntry(3, "dev", "epam"), - new JobHistoryEntry(2, "dev", "google") - )), - new Employee( - new Person("John", "Doe", 24), - Arrays.asList( - new JobHistoryEntry(4, "QA", "yandex"), - new JobHistoryEntry(2, "BA", "epam"), - new JobHistoryEntry(2, "dev", "abc") - )), - new Employee( - new Person("John", "White", 25), - Collections.singletonList( - new JobHistoryEntry(6, "QA", "epam") - )), - new Employee( - new Person("John", "Galt", 26), - Arrays.asList( - new JobHistoryEntry(3, "dev", "epam"), - new JobHistoryEntry(1, "dev", "google") - )), - new Employee( - new Person("Bob", "Doe", 27), - Arrays.asList( - new JobHistoryEntry(4, "QA", "yandex"), - new JobHistoryEntry(2, "QA", "epam"), - new JobHistoryEntry(2, "dev", "abc") - )), - new Employee( - new Person("John", "White", 28), - Collections.singletonList( - new JobHistoryEntry(666, "BA", "epam") - )), - new Employee( - new Person("John", "Galt", 29), - Arrays.asList( - new JobHistoryEntry(3, "dev", "epam"), - new JobHistoryEntry(1, "dev", "google") - )), - new Employee( - new Person("John", "Doe", 30), - Arrays.asList( - new JobHistoryEntry(4, "QA", "yandex"), - new JobHistoryEntry(2, "QA", "epam"), - new JobHistoryEntry(5, "dev", "abc") - )), - new Employee( - new Person("Bob", "White", 31), - Collections.singletonList( - new JobHistoryEntry(6, "QA", "epam") - )) + new Employee( + new Person("John", "Galt", 20), + Arrays.asList( + new JobHistoryEntry(3, "dev", "epam"), + new JobHistoryEntry(2, "dev", "google") + )), + new Employee( + new Person("John", "Doe", 21), + Arrays.asList( + new JobHistoryEntry(4, "BA", "yandex"), + new JobHistoryEntry(2, "QA", "epam"), + new JobHistoryEntry(2, "dev", "abc") + )), + new Employee( + new Person("John", "White", 22), + Collections.singletonList( + new JobHistoryEntry(6, "QA", "epam") + )), + new Employee( + new Person("John", "Galt", 23), + Arrays.asList( + new JobHistoryEntry(3, "dev", "epam"), + new JobHistoryEntry(2, "dev", "google") + )), + new Employee( + new Person("John", "Doe", 24), + Arrays.asList( + new JobHistoryEntry(4, "QA", "yandex"), + new JobHistoryEntry(2, "BA", "epam"), + new JobHistoryEntry(2, "dev", "abc") + )), + new Employee( + new Person("John", "White", 25), + Collections.singletonList( + new JobHistoryEntry(6, "QA", "epam") + )), + new Employee( + new Person("John", "Galt", 26), + Arrays.asList( + new JobHistoryEntry(3, "dev", "epam"), + new JobHistoryEntry(1, "dev", "google") + )), + new Employee( + new Person("Bob", "Doe", 27), + Arrays.asList( + new JobHistoryEntry(4, "QA", "yandex"), + new JobHistoryEntry(2, "QA", "epam"), + new JobHistoryEntry(2, "dev", "abc") + )), + new Employee( + new Person("John", "White", 28), + Collections.singletonList( + new JobHistoryEntry(666, "BA", "epam") + )), + new Employee( + new Person("John", "Galt", 29), + Arrays.asList( + new JobHistoryEntry(3, "dev", "epam"), + new JobHistoryEntry(1, "dev", "google") + )), + new Employee( + new Person("John", "Doe", 30), + Arrays.asList( + new JobHistoryEntry(4, "QA", "yandex"), + new JobHistoryEntry(2, "QA", "epam"), + new JobHistoryEntry(5, "dev", "abc") + )), + new Employee( + new Person("Bob", "White", 31), + Collections.singletonList( + new JobHistoryEntry(6, "QA", "epam") + )) ); } diff --git a/src/test/java/part2/exercise/CollectorsExercise1.java b/src/test/java/part2/exercise/CollectorsExercise1.java index 46b6765..2189b14 100755 --- a/src/test/java/part2/exercise/CollectorsExercise1.java +++ b/src/test/java/part2/exercise/CollectorsExercise1.java @@ -3,6 +3,7 @@ import data.Employee; import data.JobHistoryEntry; import data.Person; +import org.junit.Assert; import org.junit.Test; import java.util.*; @@ -16,6 +17,9 @@ import java.util.stream.IntStream; import java.util.stream.Stream; +import static java.util.stream.Collectors.collectingAndThen; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.maxBy; import static java.util.stream.Collectors.toList; public class CollectorsExercise1 { @@ -23,11 +27,13 @@ public class CollectorsExercise1 { @Test public void getTheCoolestOne() { final Map coolestByPosition = getCoolestByPosition(getEmployees()); - + final Map byPosition = getCoolestByPosition(getEmployees()); coolestByPosition.forEach((position, person) -> System.out.println(position + " -> " + person)); + Assert.assertEquals(coolestByPosition, byPosition); } private static class PersonPositionDuration { + private final Person person; private final String position; private final int duration; @@ -57,102 +63,154 @@ private Map getCoolestByPosition(List employees) { // Collectors.maxBy // Collectors.collectingAndThen // Collectors.groupingBy + return getPersonPositionDurationStream(employees).collect( + groupingBy(PersonPositionDuration::getPosition, + collectingAndThen(maxBy(Comparator.comparing(PersonPositionDuration::getDuration)), + personPositionDuration -> personPositionDuration.get().getPerson())) + ); + } - // Second option - // Collectors.toMap - // iterate twice: stream...collect(...).stream()... - // TODO - throw new UnsupportedOperationException(); + private Stream getPersonPositionDurationStream(List employees) { + return employees + .stream() + .flatMap( + e -> e.getJobHistory().stream() + .map(j -> new PersonPositionDuration(e.getPerson(), j.getPosition(), j.getDuration())) + ); } @Test public void getTheCoolestOne2() { final Map coolestByPosition = getCoolestByPosition2(getEmployees()); - + final Map byPosition2 = getCoolestByPosition2(getEmployees()); coolestByPosition.forEach((position, person) -> System.out.println(position + " -> " + person)); + + Assert.assertEquals(coolestByPosition, byPosition2); } // With the longest sum duration on this position // { John Doe, [{dev, google, 4}, {dev, epam, 4}] } предпочтительнее, чем { A B, [{dev, google, 6}, {QA, epam, 100}]} private Map getCoolestByPosition2(List employees) { - // TODO - throw new UnsupportedOperationException(); + return getPersonPositionDurationStream(employees).collect( + new Collector, Map>() { + @Override + public Supplier> supplier() { + return HashMap::new; + } + + @Override + public BiConsumer, PersonPositionDuration> accumulator() { + return (map, ppd) -> { + map.putIfAbsent(ppd.getPosition(), ppd); + PersonPositionDuration currentPpd = map.get(ppd.getPosition()); + if (ppd.getDuration() > currentPpd.getDuration()) { + map.put(ppd.getPosition(), ppd); + } + }; + } + + @Override + public BinaryOperator> combiner() { + return (m1, m2) -> { + m2.forEach((k, v) -> m1.merge(k, v, (v1, v2) -> v1.getDuration() > v2.getDuration() ? v1 : v2)); + return m1; + }; + } + + @Override + public Function, Map> finisher() { + return map -> map.entrySet() + .stream() + .collect( + Collectors.toMap( + Map.Entry::getKey, + item -> item.getValue().getPerson() + ) + ); + } + + @Override + public Set characteristics() { + return Collections.unmodifiableSet(EnumSet.of(Characteristics.UNORDERED)); + } + } + ); } private List getEmployees() { return Arrays.asList( - new Employee( - new Person("John", "Galt", 20), - Arrays.asList( - new JobHistoryEntry(3, "dev", "epam"), - new JobHistoryEntry(2, "dev", "google") - )), - new Employee( - new Person("John", "Doe", 21), - Arrays.asList( - new JobHistoryEntry(4, "BA", "yandex"), - new JobHistoryEntry(2, "QA", "epam"), - new JobHistoryEntry(2, "dev", "abc") - )), - new Employee( - new Person("John", "White", 22), - Collections.singletonList( - new JobHistoryEntry(6, "QA", "epam") - )), - new Employee( - new Person("John", "Galt", 23), - Arrays.asList( - new JobHistoryEntry(3, "dev", "epam"), - new JobHistoryEntry(2, "dev", "google") - )), - new Employee( - new Person("John", "Doe", 24), - Arrays.asList( - new JobHistoryEntry(4, "QA", "yandex"), - new JobHistoryEntry(2, "BA", "epam"), - new JobHistoryEntry(2, "dev", "abc") - )), - new Employee( - new Person("John", "White", 25), - Collections.singletonList( - new JobHistoryEntry(6, "QA", "epam") - )), - new Employee( - new Person("John", "Galt", 26), - Arrays.asList( - new JobHistoryEntry(3, "dev", "epam"), - new JobHistoryEntry(1, "dev", "google") - )), - new Employee( - new Person("Bob", "Doe", 27), - Arrays.asList( - new JobHistoryEntry(4, "QA", "yandex"), - new JobHistoryEntry(2, "QA", "epam"), - new JobHistoryEntry(2, "dev", "abc") - )), - new Employee( - new Person("John", "White", 28), - Collections.singletonList( - new JobHistoryEntry(6, "BA", "epam") - )), - new Employee( - new Person("John", "Galt", 29), - Arrays.asList( - new JobHistoryEntry(3, "dev", "epam"), - new JobHistoryEntry(1, "dev", "google") - )), - new Employee( - new Person("John", "Doe", 30), - Arrays.asList( - new JobHistoryEntry(4, "QA", "yandex"), - new JobHistoryEntry(2, "QA", "epam"), - new JobHistoryEntry(5, "dev", "abc") - )), - new Employee( - new Person("Bob", "White", 31), - Collections.singletonList( - new JobHistoryEntry(6, "QA", "epam") - )) + new Employee( + new Person("John", "Galt", 20), + Arrays.asList( + new JobHistoryEntry(3, "dev", "epam"), + new JobHistoryEntry(2, "dev", "google") + )), + new Employee( + new Person("John", "Doe", 21), + Arrays.asList( + new JobHistoryEntry(4, "BA", "yandex"), + new JobHistoryEntry(2, "QA", "epam"), + new JobHistoryEntry(2, "dev", "abc") + )), + new Employee( + new Person("John", "White", 22), + Collections.singletonList( + new JobHistoryEntry(6, "QA", "epam") + )), + new Employee( + new Person("John", "Galt", 23), + Arrays.asList( + new JobHistoryEntry(3, "dev", "epam"), + new JobHistoryEntry(2, "dev", "google") + )), + new Employee( + new Person("John", "Doe", 24), + Arrays.asList( + new JobHistoryEntry(4, "QA", "yandex"), + new JobHistoryEntry(2, "BA", "epam"), + new JobHistoryEntry(2, "dev", "abc") + )), + new Employee( + new Person("John", "White", 25), + Collections.singletonList( + new JobHistoryEntry(6, "QA", "epam") + )), + new Employee( + new Person("John", "Galt", 26), + Arrays.asList( + new JobHistoryEntry(3, "dev", "epam"), + new JobHistoryEntry(1, "dev", "google") + )), + new Employee( + new Person("Bob", "Doe", 27), + Arrays.asList( + new JobHistoryEntry(4, "QA", "yandex"), + new JobHistoryEntry(2, "QA", "epam"), + new JobHistoryEntry(2, "dev", "abc") + )), + new Employee( + new Person("John", "White", 28), + Collections.singletonList( + new JobHistoryEntry(6, "BA", "epam") + )), + new Employee( + new Person("John", "Galt", 29), + Arrays.asList( + new JobHistoryEntry(3, "dev", "epam"), + new JobHistoryEntry(1, "dev", "google") + )), + new Employee( + new Person("John", "Doe", 30), + Arrays.asList( + new JobHistoryEntry(4, "QA", "yandex"), + new JobHistoryEntry(2, "QA", "epam"), + new JobHistoryEntry(5, "dev", "abc") + )), + new Employee( + new Person("Bob", "White", 31), + Collections.singletonList( + new JobHistoryEntry(6, "QA", "epam") + )) ); } diff --git a/src/test/java/part2/exercise/CollectorsExercise2.java b/src/test/java/part2/exercise/CollectorsExercise2.java index 00fda00..e66fc85 100755 --- a/src/test/java/part2/exercise/CollectorsExercise2.java +++ b/src/test/java/part2/exercise/CollectorsExercise2.java @@ -3,6 +3,7 @@ import data.Employee; import data.JobHistoryEntry; import data.Person; +import org.junit.Assert; import org.junit.Test; import java.util.*; @@ -26,15 +27,15 @@ private static String generateString() { final int length = ThreadLocalRandom.current().nextInt(maxLength) + 1; return IntStream.range(0, length) - .mapToObj(letters::charAt) - .map(Object::toString) - .collect(Collectors.joining()); + .mapToObj(letters::charAt) + .map(Object::toString) + .collect(Collectors.joining()); } private static String[] generateStringArray(int length) { return Stream.generate(CollectorsExercise2::generateString) - .limit(length) - .toArray(String[]::new); + .limit(length) + .toArray(String[]::new); } public static String pickString(String[] array) { @@ -42,6 +43,7 @@ public static String pickString(String[] array) { } public static class Key { + private final String id; public Key(String id) { @@ -54,8 +56,12 @@ public String getId() { @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } Key key = (Key) o; @@ -70,6 +76,7 @@ public int hashCode() { } public static class Value { + private final String keyId; public Value(String keyId) { @@ -82,6 +89,7 @@ public String getKeyId() { } public static class Pair { + private final Key key; private final Value value; @@ -103,16 +111,18 @@ public static List generatePairs(int idCount, int length) { final String[] ids = generateStringArray(idCount); return Stream.generate(() -> new Pair(new Key(pickString(ids)), new Value(pickString(ids)))) - .limit(length) - .collect(toList()); + .limit(length) + .collect(toList()); } private static class SubResult { + private final Map> subResult; private final Map> knownKeys; private final Map> valuesWithoutKeys; - public SubResult(Map> subResult, Map> knownKeys, Map> valuesWithoutKeys) { + public SubResult(Map> subResult, Map> knownKeys, + Map> valuesWithoutKeys) { this.subResult = subResult; this.knownKeys = knownKeys; this.valuesWithoutKeys = valuesWithoutKeys; @@ -132,6 +142,7 @@ public Map> getKnownKeys() { } private static class MapPair { + private final Map keyById; private final Map> valueById; @@ -166,92 +177,87 @@ BinaryOperator mapMerger(BinaryOperator mergeFunction) { @Test public void collectKeyValueMap() { final List pairs = generatePairs(10, 100); + Map keyMap1 = pairs.stream() + .collect( + Collectors.toMap( + p -> p.getKey().getId(), + Pair::getKey, + (v1, v2) -> v1 + ) + ); + + Map> valuesMap1 = pairs.stream() + .collect( + Collectors.groupingBy( + p -> p.getValue().getKeyId(), + Collectors.mapping(Pair::getValue, toList()) + ) + ); + + Map> keyValuesMap1 = valuesMap1.entrySet().stream() + .collect( + Collectors.toMap( + p -> keyMap1.get(p.getKey()), + Map.Entry::getValue + ) + ); - // В два прохода - // final Map keyMap1 = pairs.stream()... - - // final Map> valuesMap1 = pairs.stream()... - - // В каждом Map.Entry id ключа должно совпадать с keyId для каждого значения в списке - // final Map> keyValuesMap1 = valueMap1.entrySet().stream()... - - // В 1 проход в 2 Map с использованием MapPair и mapMerger final MapPair res2 = pairs.stream() - .collect(new Collector() { - @Override - public Supplier supplier() { - // TODO - throw new UnsupportedOperationException(); - } - - @Override - public BiConsumer accumulator() { - // TODO add key and value to maps - throw new UnsupportedOperationException(); - } - - @Override - public BinaryOperator combiner() { - // TODO use mapMerger - throw new UnsupportedOperationException(); - } - - @Override - public Function finisher() { - return Function.identity(); - } - - @Override - public Set characteristics() { - return Collections.unmodifiableSet(EnumSet.of( - Characteristics.UNORDERED, - Characteristics.IDENTITY_FINISH)); - } - }); + .collect(new Collector() { + @Override + public Supplier supplier() { + return MapPair::new; + } + + @Override + public BiConsumer accumulator() { + return (mp, p) -> { + mp.getKeyById().computeIfAbsent(p.getKey().getId(), q -> p.getKey()); + mp.getValueById().computeIfAbsent(p.getValue().getKeyId(), q -> new ArrayList<>()) + .add(p.getValue()); + }; + } + + @Override + public BinaryOperator combiner() { + return (mp1, mp2) -> { + BinaryOperator> biOpKey = mapMerger((v1, v2) -> v1); + Map mapKey = biOpKey.apply(mp1.getKeyById(), mp2.getKeyById()); + + BinaryOperator>> biOpValue = mapMerger((v1, v2) -> { + v1.addAll(v2); + return v1; + }); + Map> mapValue = biOpValue.apply(mp1.getValueById(), mp2.getValueById()); + + return new MapPair(mapKey, mapValue); + }; + } + + @Override + public Function finisher() { + return Function.identity(); + } + + @Override + public Set characteristics() { + return Collections.unmodifiableSet(EnumSet.of( + Characteristics.UNORDERED, + Characteristics.IDENTITY_FINISH)); + } + }); final Map keyMap2 = res2.getKeyById(); final Map> valuesMap2 = res2.getValueById(); - // final Map> keyValuesMap2 = valueMap2.entrySet().stream()... - - // Получение результата сразу: - - final SubResult res3 = pairs.stream() - .collect(new Collector() { - @Override - public Supplier supplier() { - // TODO - throw new UnsupportedOperationException(); - } - - @Override - public BiConsumer accumulator() { - // TODO add key to map, then check value.keyId and add it to one of maps - throw new UnsupportedOperationException(); - } - - @Override - public BinaryOperator combiner() { - // TODO use mapMerger, then check all valuesWithoutKeys - throw new UnsupportedOperationException(); - } - - @Override - public Function finisher() { - // TODO use mapMerger, then check all valuesWithoutKeys - throw new UnsupportedOperationException(); - } - - @Override - public Set characteristics() { - return Collections.unmodifiableSet(EnumSet.of( - Characteristics.UNORDERED)); - } - }); - - final Map> keyValuesMap3 = res3.getSubResult(); - - // compare results + final Map> keyValuesMap2 = valuesMap2.entrySet().stream().collect( + Collectors.toMap( + p -> keyMap2.get(p.getKey()), + Map.Entry::getValue + ) + ); + + Assert.assertEquals(keyValuesMap1, keyValuesMap2); } } diff --git a/src/test/java/part3/exercise/lambda/LambdaExercise.java b/src/test/java/part3/exercise/lambda/LambdaExercise.java index 752e1f2..3a4fc8f 100755 --- a/src/test/java/part3/exercise/lambda/LambdaExercise.java +++ b/src/test/java/part3/exercise/lambda/LambdaExercise.java @@ -3,6 +3,7 @@ import data.Person; import org.junit.Test; +import java.util.Objects; import java.util.function.Function; import java.util.function.Predicate; import java.util.function.Supplier; @@ -15,19 +16,26 @@ public class LambdaExercise { public void supply() { final Person person = new Person("John", "Galt", 30); - final Supplier getPerson = null; // TODO return person from Supplier + final Supplier getPerson = () -> person; // TODO return person from Supplier assertEquals(person, getPerson.get()); } @Test public void function() { - final Function getPersonName1 = null; // TODO get the name of person using expression lambda + final Function + getPersonName1 = + name -> name.getFirstName(); // TODO get the name of person using expression lambda - final Function getPersonName2 = null; // TODO get the name of person using method reference + final Function + getPersonName2 = + Person::getFirstName; // TODO get the name of person using method reference // TODO get the name of person and log it to System.out using statement lambda: {} - final Function getPersonNameAndLogIt = null; + final Function getPersonNameAndLogIt = name -> { + System.out.println(name); + return name.getFirstName(); + }; final Person person = new Person("John", "Galt", 30); @@ -38,19 +46,20 @@ public void function() { @Test public void combineFunctions() { - final Function getPersonName = null; // TODO get the name of person + final Function getPersonName = Person::getFirstName; // TODO get the name of person assertEquals("John", getPersonName.apply(new Person("John", "Galt", 30))); - final Function getStringLength = null; // TODO get string length + final Function getStringLength = String::length; // TODO get string length assertEquals(Integer.valueOf(3), getStringLength.apply("ABC")); // TODO get person name length using getPersonName and getStringLength without andThen - final Function getPersonNameLength1 = null; + final Function getPersonNameLength1 = t -> getStringLength.apply(getPersonName.apply(t)); + ; // TODO get person name length using getPersonName and getStringLength with andThen - final Function getPersonNameLength2 = null; + final Function getPersonNameLength2 = getPersonName.andThen(getStringLength); final Person person = new Person("John", "Galt", 30); @@ -59,6 +68,7 @@ public void combineFunctions() { } private interface PersonFactory { + Person create(String name, String lastName, int age); } @@ -68,22 +78,21 @@ private Person createPerson(PersonFactory pf) { // ((T -> R), (R -> boolean)) -> (T -> boolean) private Predicate combine(Function f, Predicate p) { - // TODO - throw new UnsupportedOperationException(); + return (T t) -> p.test(f.apply(t)); } @Test public void methodReference() { // TODO use only method reverences here. - final Person person = createPerson(null); // TODO + final Person person = createPerson(Person::new); // TODO assertEquals(new Person("John", "Galt", 66), person); - final Function getPersonName = null; // TODO + final Function getPersonName = Person::getFirstName; // TODO assertEquals("John", getPersonName.apply(person)); - final Predicate isJohnString = null; // TODO using method reference check that "John" equals string parameter + final Predicate isJohnString = "John"::equals ; // TODO using method reference check that "John" equals string parameter final Predicate isJohnPerson = combine(getPersonName, isJohnString); diff --git a/src/test/java/part3/exercise/stream/StreamsExercise.java b/src/test/java/part3/exercise/stream/StreamsExercise.java index 4e2d54b..eb47aee 100755 --- a/src/test/java/part3/exercise/stream/StreamsExercise.java +++ b/src/test/java/part3/exercise/stream/StreamsExercise.java @@ -8,9 +8,23 @@ import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.Map; - +import java.util.Optional; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.function.ToIntFunction; +import java.util.stream.Collector; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static java.util.stream.Collectors.collectingAndThen; +import static java.util.stream.Collectors.groupingBy; +import static java.util.stream.Collectors.mapping; +import static java.util.stream.Collectors.maxBy; +import static java.util.stream.Collectors.summingInt; +import static java.util.stream.Collectors.toList; import static org.junit.Assert.assertEquals; public class StreamsExercise { @@ -19,7 +33,10 @@ public class StreamsExercise { public void getAllJobHistoryEntries() { final List employees = getEmployees(); - final List jobHistoryEntries = null; // TODO + final List + jobHistoryEntries = employees.stream(). + flatMap(employee -> employee.getJobHistory().stream()) + .collect(toList()); assertEquals(22, jobHistoryEntries.size()); } @@ -29,12 +46,16 @@ public void getSumDuration() { // sum all durations for all persons final List employees = getEmployees(); - final int sumDurations = 0; // TODO + final int + sumDurations = + employees.stream().flatMap(employee -> employee.getJobHistory().stream()) + .mapToInt(JobHistoryEntry::getDuration).sum(); assertEquals(72, sumDurations); } - private static class PersonEmployer{ + private static class PersonEmployer { + private final Person person; private final String employer; @@ -54,9 +75,9 @@ public String getEmployer() { @Override public String toString() { return new ToStringBuilder(this) - .append("person", person) - .append("employer", employer) - .toString(); + .append("person", person) + .append("employer", employer) + .toString(); } } @@ -64,7 +85,15 @@ public String toString() { public void indexPersonsByEmployer1() { final List employees = getEmployees(); - final Map> index = null; // TODO + final Map> index = employees.stream() + .flatMap(employee -> employee.getJobHistory().stream() + .map(JobHistoryEntry -> new PersonEmployer(employee.getPerson(), JobHistoryEntry.getEmployer()))) + .collect( + groupingBy( + PersonEmployer::getEmployer, + mapping(Function.identity(), toList()) + ) + ); assertEquals(11, index.get("epam").size()); } @@ -73,12 +102,21 @@ public void indexPersonsByEmployer1() { public void indexPersonsByEmployer2() { final List employees = getEmployees(); - final Map> index = null; // TODO + final Map> index = employees.stream() + .flatMap(employee -> employee.getJobHistory().stream() + .map(JobHistoryEntry -> new PersonEmployer(employee.getPerson(), JobHistoryEntry.getEmployer()))) + .collect( + groupingBy( + PersonEmployer::getEmployer, + mapping(PersonEmployer::getPerson, toList()) + ) + ); // assertEquals(11, index.get("epam").size()); } private static class PersonDuration { + private final Person person; private final int duration; @@ -98,28 +136,33 @@ public int getDuration() { @Override public String toString() { return new ToStringBuilder(this) - .append("person", person) - .append("duration", duration) - .toString(); + .append("person", person) + .append("duration", duration) + .toString(); } } private PersonDuration sumAllPersonDurations(Employee e) { - // TODO - throw new UnsupportedOperationException(); + int duration = e.getJobHistory().stream() + .mapToInt(JobHistoryEntry::getDuration) + .sum(); + return new PersonDuration(e.getPerson(), duration); } + @Test public void getSumPersonDuration() { // sum all durations for each person final List employees = getEmployees(); - final Map personDuration = null; // TODO use sumAllPersonDurations + final Map personDuration = employees.stream() + .collect(Collectors.toMap(Employee::getPerson, e -> sumAllPersonDurations(e).getDuration())); assertEquals(Integer.valueOf(8), personDuration.get(new Person("John", "Doe", 24))); } private static class PersonPositionIndex { + private final Person person; private final Map durationByPositionIndex; @@ -138,20 +181,26 @@ public Map getDurationByPositionIndex() { } private static PersonPositionIndex getPersonPositionIndex(Employee e) { - // TODO - throw new UnsupportedOperationException(); + final Map durationByPostion = e.getJobHistory() + .stream() + .collect(Collectors.toMap(JobHistoryEntry::getPosition, JobHistoryEntry::getDuration, + (integer, integer2) -> integer + integer2)); + + return new PersonPositionIndex(e.getPerson(), durationByPostion); } @Test public void getSumDurationsForPersonByPosition() { final List employees = getEmployees(); - final List personIndexes = null; // TODO use getPersonPositionIndex + final List personIndexes = employees.stream() + .map(StreamsExercise::getPersonPositionIndex).collect(toList()); assertEquals(1, personIndexes.get(3).getDurationByPositionIndex().size()); } private static class PersonPositionDuration { + private final Person person; private final String position; private final int duration; @@ -179,8 +228,12 @@ public int getDuration() { public void getDurationsForEachPersonByPosition() { final List employees = getEmployees(); - final List personPositionDurations = null; // TODO - + final List personPositionDurations = employees.stream() + .flatMap(employee -> employee.getJobHistory().stream() + .collect(groupingBy(JobHistoryEntry::getPosition, summingInt(JobHistoryEntry::getDuration))) + .entrySet().stream() + .map(entry -> new PersonPositionDuration(employee.getPerson(), entry.getKey(), entry.getValue()))) + .collect(Collectors.toList()); assertEquals(17, personPositionDurations.size()); } @@ -190,8 +243,21 @@ public void getCoolestPersonByPosition1() { // Get person with max duration on given position final List employees = getEmployees(); - final Map coolestPersonByPosition = null;// TODO - + final Map coolestPersonByPosition = employees.stream() + .flatMap( + employee -> employee.getJobHistory().stream() + .collect( + groupingBy( + JobHistoryEntry::getPosition, + summingInt(JobHistoryEntry::getDuration) + ) + ) + .entrySet().stream() + .map(entry -> new PersonPositionDuration(employee.getPerson(), entry.getKey(), entry.getValue()))) + .collect( + Collectors.toMap(PersonPositionDuration::getPosition, Function.identity(), + BinaryOperator.maxBy(Comparator.comparing(PersonPositionDuration::getDuration))) + ); assertEquals(new Person("John", "White", 22), coolestPersonByPosition.get("QA").getPerson()); } @@ -201,83 +267,100 @@ public void getCoolestPersonByPosition2() { // Get person with max duration on given position final List employees = getEmployees(); - final Map coolestPersonByPosition = null; // TODO - + final Map coolestPersonByPosition = employees.stream() + .flatMap( + employee -> employee.getJobHistory().stream() + .collect( + groupingBy( + JobHistoryEntry::getPosition, + summingInt(JobHistoryEntry::getDuration) + ) + ) + .entrySet().stream() + + .map(entry -> new PersonPositionDuration(employee.getPerson(), entry.getKey(), entry.getValue()))) + .collect( + groupingBy( + PersonPositionDuration::getPosition, + collectingAndThen(maxBy(Comparator.comparing(PersonPositionDuration::getDuration)), + p -> p.get().getPerson()) + ) + ); assertEquals(new Person("John", "White", 22), coolestPersonByPosition.get("QA")); } private List getEmployees() { return Arrays.asList( - new Employee( - new Person("John", "Galt", 20), - Collections.emptyList()), - new Employee( - new Person("John", "Doe", 21), - Arrays.asList( - new JobHistoryEntry(4, "BA", "yandex"), - new JobHistoryEntry(2, "QA", "epam"), - new JobHistoryEntry(2, "dev", "abc") - )), - new Employee( - new Person("John", "White", 22), - Collections.singletonList( - new JobHistoryEntry(6, "QA", "epam") - )), - new Employee( - new Person("John", "Galt", 23), - Arrays.asList( - new JobHistoryEntry(3, "dev", "epam"), - new JobHistoryEntry(2, "dev", "google") - )), - new Employee( - new Person("John", "Doe", 24), - Arrays.asList( - new JobHistoryEntry(4, "QA", "yandex"), - new JobHistoryEntry(2, "BA", "epam"), - new JobHistoryEntry(2, "dev", "abc") - )), - new Employee( - new Person("John", "White", 25), - Collections.singletonList( - new JobHistoryEntry(6, "QA", "epam") - )), - new Employee( - new Person("John", "Galt", 26), - Arrays.asList( - new JobHistoryEntry(3, "dev", "epam"), - new JobHistoryEntry(1, "dev", "google") - )), - new Employee( - new Person("Bob", "Doe", 27), - Arrays.asList( - new JobHistoryEntry(4, "QA", "yandex"), - new JobHistoryEntry(2, "QA", "epam"), - new JobHistoryEntry(2, "dev", "abc") - )), - new Employee( - new Person("John", "White", 28), - Collections.singletonList( - new JobHistoryEntry(6, "BA", "epam") - )), - new Employee( - new Person("John", "Galt", 29), - Arrays.asList( - new JobHistoryEntry(3, "dev", "epam"), - new JobHistoryEntry(1, "dev", "google") - )), - new Employee( - new Person("John", "Doe", 30), - Arrays.asList( - new JobHistoryEntry(4, "QA", "yandex"), - new JobHistoryEntry(2, "QA", "epam"), - new JobHistoryEntry(5, "dev", "abc") - )), - new Employee( - new Person("Bob", "White", 31), - Collections.singletonList( - new JobHistoryEntry(6, "QA", "epam") - )) + new Employee( + new Person("John", "Galt", 20), + Collections.emptyList()), + new Employee( + new Person("John", "Doe", 21), + Arrays.asList( + new JobHistoryEntry(4, "BA", "yandex"), + new JobHistoryEntry(2, "QA", "epam"), + new JobHistoryEntry(2, "dev", "abc") + )), + new Employee( + new Person("John", "White", 22), + Collections.singletonList( + new JobHistoryEntry(6, "QA", "epam") + )), + new Employee( + new Person("John", "Galt", 23), + Arrays.asList( + new JobHistoryEntry(3, "dev", "epam"), + new JobHistoryEntry(2, "dev", "google") + )), + new Employee( + new Person("John", "Doe", 24), + Arrays.asList( + new JobHistoryEntry(4, "QA", "yandex"), + new JobHistoryEntry(2, "BA", "epam"), + new JobHistoryEntry(2, "dev", "abc") + )), + new Employee( + new Person("John", "White", 25), + Collections.singletonList( + new JobHistoryEntry(6, "QA", "epam") + )), + new Employee( + new Person("John", "Galt", 26), + Arrays.asList( + new JobHistoryEntry(3, "dev", "epam"), + new JobHistoryEntry(1, "dev", "google") + )), + new Employee( + new Person("Bob", "Doe", 27), + Arrays.asList( + new JobHistoryEntry(4, "QA", "yandex"), + new JobHistoryEntry(2, "QA", "epam"), + new JobHistoryEntry(2, "dev", "abc") + )), + new Employee( + new Person("John", "White", 28), + Collections.singletonList( + new JobHistoryEntry(6, "BA", "epam") + )), + new Employee( + new Person("John", "Galt", 29), + Arrays.asList( + new JobHistoryEntry(3, "dev", "epam"), + new JobHistoryEntry(1, "dev", "google") + )), + new Employee( + new Person("John", "Doe", 30), + Arrays.asList( + new JobHistoryEntry(4, "QA", "yandex"), + new JobHistoryEntry(2, "QA", "epam"), + new JobHistoryEntry(5, "dev", "abc") + )), + new Employee( + new Person("Bob", "White", 31), + Collections.singletonList( + new JobHistoryEntry(6, "QA", "epam") + )) ); }