diff --git a/src/main/java/data/Generator.java b/src/main/java/data/Generator.java index cbd46ea..f98fd1b 100644 --- a/src/main/java/data/Generator.java +++ b/src/main/java/data/Generator.java @@ -60,7 +60,10 @@ public static Employee generateEmployee() { } public static List generateEmployeeList() { - // TODO - throw new UnsupportedOperationException(); + final int maxLength = 10; + final int length = ThreadLocalRandom.current().nextInt(maxLength) + 1; + return Stream.generate(Generator::generateEmployee) + .limit(length) + .collect(toList()); } } diff --git a/src/test/java/part1/exercise/StreamsExercise1.java b/src/test/java/part1/exercise/StreamsExercise1.java index 02dd2da..66d9bb1 100755 --- a/src/test/java/part1/exercise/StreamsExercise1.java +++ b/src/test/java/part1/exercise/StreamsExercise1.java @@ -6,15 +6,12 @@ import org.junit.Test; import java.util.*; -import java.util.concurrent.ThreadLocalRandom; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; import static data.Generator.generateEmployeeList; import static java.util.stream.Collectors.groupingBy; -import static java.util.stream.Collectors.mapping; +import static java.util.stream.Collectors.summingInt; import static java.util.stream.Collectors.toList; +import static org.junit.Assert.assertEquals; public class StreamsExercise1 { // https://youtu.be/kxgo7Y4cdA8 Сергей Куксенко и Алексей Шипилёв — Через тернии к лямбдам, часть 1 @@ -25,14 +22,45 @@ public class StreamsExercise1 { @Test public void getAllEpamEmployees() { - List epamEmployees = null;// TODO all persons with experience in epam - throw new UnsupportedOperationException(); + List employees = generateEmployeeList(); + + List personsList = employees.stream() + .filter(e -> e.getJobHistory().stream() + .map(JobHistoryEntry::getEmployer) + .anyMatch(em -> em.equals("epam"))) + .map(Employee::getPerson) + .collect(toList()); + + List expectedPersonList = new ArrayList<>(); + for (Employee e : employees) { + for (JobHistoryEntry j : e.getJobHistory()) { + if (j.getEmployer().equals("epam")) { + expectedPersonList.add(e.getPerson()); + break; + } + } + } + + assertEquals(expectedPersonList, personsList); } @Test public void getEmployeesStartedFromEpam() { - List epamEmployees = null;// TODO all persons with first experience in epam - throw new UnsupportedOperationException(); + List employees = generateEmployeeList(); + + List personList = employees.stream() + .filter(e -> e.getJobHistory().get(0).getEmployer().equals("epam")) + .map(Employee::getPerson) + .collect(toList()); + + List epamEmployeesExpected = new ArrayList<>(); + for (Employee e : employees) { + if (e.getJobHistory().get(0).getEmployer().equals("epam")) { + epamEmployeesExpected.add(e.getPerson()); + } + } + + assertEquals(epamEmployeesExpected, personList); } @Test @@ -49,11 +77,13 @@ public void sumEpamDurations() { } } - // TODO - throw new UnsupportedOperationException(); + int result = employees.stream() + .flatMap(e -> e.getJobHistory().stream()) + .filter(j -> j.getEmployer().equals("epam")) + .mapToInt(JobHistoryEntry::getDuration) + .sum(); - // int result = ??? - // assertEquals(expected, result); + assertEquals(expected, result); } } diff --git a/src/test/java/part1/exercise/StreamsExercise2.java b/src/test/java/part1/exercise/StreamsExercise2.java index 5be9d38..43cfc2e 100755 --- a/src/test/java/part1/exercise/StreamsExercise2.java +++ b/src/test/java/part1/exercise/StreamsExercise2.java @@ -5,10 +5,14 @@ import data.Person; import org.junit.Test; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Comparator; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; import java.util.stream.Stream; import static data.Generator.generateEmployeeList; @@ -22,23 +26,86 @@ public class StreamsExercise2 { // 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; + private final int duration; + + private PersonEmployerPair(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 employersStuffLists() { - Map> employersStuffLists = null;// TODO - throw new UnsupportedOperationException(); + Map> employersStuffLists = getEmployees().stream() + .flatMap(employee -> employee.getJobHistory().stream() + .map(j -> new PersonEmployerPair(employee.getPerson(), j.getEmployer(), j.getDuration()))) + .collect(Collectors.groupingBy( + PersonEmployerPair::getEmployer, + mapping(PersonEmployerPair::getPerson, toList()) + )); + + List personList = new ArrayList<>(); + personList.add(new Person("John", "Doe", 21)); + personList.add(new Person("John", "Doe", 24)); + personList.add(new Person("Bob", "Doe", 27)); + personList.add(new Person("John", "Doe", 30)); + + assertEquals(personList, employersStuffLists.get("abc")); } @Test public void indexByFirstEmployer() { - Map> employeesIndex = null;// TODO - throw new UnsupportedOperationException(); + Map> employeesIndex = getEmployees().stream() + .map(employee -> new PersonEmployerPair(employee.getPerson(), + employee.getJobHistory().get(0).getEmployer(), + employee.getJobHistory().get(0).getDuration())) + .collect(Collectors.groupingBy( + PersonEmployerPair::getEmployer, + mapping(PersonEmployerPair::getPerson, toList()) + )); + + List personList = new ArrayList<>(); + personList.add(new Person("John", "Galt", 20)); + personList.add(new Person("John", "White", 22)); + personList.add(new Person("John", "Galt", 23)); + personList.add(new Person("John", "White", 25)); + personList.add(new Person("John", "Galt", 26)); + personList.add(new Person("John", "White", 28)); + personList.add(new Person("John", "Galt", 29)); + personList.add(new Person("Bob", "White", 31)); + + assertEquals(personList, employeesIndex.get("epam")); + } @Test public void greatestExperiencePerEmployer() { - Map employeesIndex = null;// TODO + Map employeesIndex = getEmployees().stream() + .flatMap(employee -> employee.getJobHistory().stream() + .map(j -> new PersonEmployerPair(employee.getPerson(), j.getEmployer(), j.getDuration()))) + .collect(Collectors.groupingBy( + PersonEmployerPair::getEmployer, + Collectors.collectingAndThen( + Collectors.maxBy(Comparator.comparingInt(PersonEmployerPair::getDuration)), + p -> p.get().getPerson()) + )); assertEquals(new Person("John", "White", 28), employeesIndex.get("epam")); } @@ -46,78 +113,78 @@ public void greatestExperiencePerEmployer() { 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..96ae277 100755 --- a/src/test/java/part2/exercise/CollectorsExercise1.java +++ b/src/test/java/part2/exercise/CollectorsExercise1.java @@ -6,17 +6,21 @@ import org.junit.Test; import java.util.*; -import java.util.concurrent.ThreadLocalRandom; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Collector; import java.util.stream.Collectors; -import java.util.stream.IntStream; import java.util.stream.Stream; -import static java.util.stream.Collectors.toList; +import static java.util.Comparator.comparing; +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.summingInt; +import static java.util.stream.Collectors.toMap; +import static org.junit.Assert.assertEquals; public class CollectorsExercise1 { @@ -28,6 +32,7 @@ public void getTheCoolestOne() { } private static class PersonPositionDuration { + private final Person person; private final String position; private final int duration; @@ -58,102 +63,182 @@ private Map getCoolestByPosition(List employees) { // Collectors.collectingAndThen // Collectors.groupingBy + final Stream persons = employees.stream() + .flatMap(e -> e.getJobHistory().stream() + .map(j -> new PersonPositionDuration(e.getPerson(), j.getPosition(), j.getDuration()))); + + Map option1 = persons + .collect(Collectors.groupingBy( + PersonPositionDuration::getPosition, + collectingAndThen( + maxBy(comparing(PersonPositionDuration::getDuration)), + p -> p.get().getPerson()) + )); + // Second option // Collectors.toMap // iterate twice: stream...collect(...).stream()... - // TODO - throw new UnsupportedOperationException(); + + Map positionDurationMap = persons + .collect(toMap( + PersonPositionDuration::getPosition, + Function.identity(), + BinaryOperator.maxBy(comparing(PersonPositionDuration::getDuration)) + )); + + Map option2 = positionDurationMap.entrySet().stream() + .collect(toMap(Map.Entry::getKey, + employee -> employee.getValue().getPerson())); + + //third option + Map option3 = persons + .collect(new Collector, Map>() { + @Override + public Supplier> supplier() { + return HashMap::new; + } + + @Override + public BiConsumer, PersonPositionDuration> accumulator() { + return (map, person) -> map.merge( + person.getPosition(), + person, + (ppd1, ppd2) -> ppd1.getDuration() > ppd2.getDuration() ? ppd1 : ppd2); + } + + @Override + public BinaryOperator> combiner() { + return (map1, map2) -> { + map2.forEach((key, value) -> map1.merge(key, value, (ppd1, ppd2) -> + ppd1.getDuration() > ppd2.getDuration() ? ppd1 : ppd2)); + return map1; + }; + } + + @Override + public Function, Map> finisher() { + return (map) -> map.entrySet().stream() + .collect(toMap(Map.Entry::getKey, + employee -> employee.getValue().getPerson())); + } + + @Override + public Set characteristics() { + return Collections.emptySet(); + } + }); + + return option1; } @Test public void getTheCoolestOne2() { final Map coolestByPosition = getCoolestByPosition2(getEmployees()); - coolestByPosition.forEach((position, person) -> System.out.println(position + " -> " + person)); + assertEquals(new Person("John", "Doe", 30), coolestByPosition.get("QA")); + assertEquals(new Person("John", "Galt", 26), coolestByPosition.get("dev")); + assertEquals(new Person("John", "Doe", 24), coolestByPosition.get("BA")); } - // With the longest sum duration on this position - // { John Doe, [{dev, google, 4}, {dev, epam, 4}] } предпочтительнее, чем { A B, [{dev, google, 6}, {QA, epam, 100}]} +// 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(); + Map> map = employees.stream() + .flatMap(this::positionDuration) + .collect(groupingBy(PersonPositionDuration::getPosition)); + + return map.entrySet().stream() + .collect(toMap(Map.Entry::getKey, + ppd -> ppd.getValue().stream() + .reduce((ppd1, ppd2) -> ppd1.getDuration() > ppd2.getDuration() ? ppd1 : ppd2) + .get() + .getPerson())); } - private List getEmployees() { - return Arrays.asList( + private Stream positionDuration(Employee employee){ + Map mapEmployee = employee.getJobHistory().stream() + .collect(groupingBy(JobHistoryEntry::getPosition, + summingInt(JobHistoryEntry::getDuration))); + + return mapEmployee.entrySet().stream() + .map(e -> new PersonPositionDuration(employee.getPerson(), e.getKey(), e.getValue())); + } + + 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 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 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 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 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 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 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 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 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 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 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 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 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..ddce3e7 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.*; @@ -16,6 +17,7 @@ import java.util.stream.IntStream; import java.util.stream.Stream; +import static java.util.Collections.singletonList; import static java.util.stream.Collectors.toList; public class CollectorsExercise2 { @@ -26,15 +28,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 +44,7 @@ public static String pickString(String[] array) { } public static class Key { + private final String id; public Key(String id) { @@ -54,8 +57,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 +77,7 @@ public int hashCode() { } public static class Value { + private final String keyId; public Value(String keyId) { @@ -82,6 +90,7 @@ public String getKeyId() { } public static class Pair { + private final Key key; private final Value value; @@ -103,16 +112,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 +143,7 @@ public Map> getKnownKeys() { } private static class MapPair { + private final Map keyById; private final Map> valueById; @@ -168,90 +180,111 @@ public void collectKeyValueMap() { final List pairs = generatePairs(10, 100); // В два прохода - // final Map keyMap1 = pairs.stream()... - - // final Map> valuesMap1 = pairs.stream()... + final Map keyMap1 = pairs.stream() + .map(Pair::getKey) + .collect(Collectors.toMap(Key::getId, Function.identity(), (k1, k2) -> k1)); + final Map> valueMap1 = pairs.stream() + .map(Pair::getValue) + .collect(Collectors.groupingBy(Value::getKeyId)); // В каждом Map.Entry id ключа должно совпадать с keyId для каждого значения в списке - // final Map> keyValuesMap1 = valueMap1.entrySet().stream()... - + final Map> keyValuesMap1 = valueMap1.entrySet().stream() + .collect(Collectors.toMap(e -> keyMap1.get(e.getKey()), + Map.Entry::getValue, + (list1, list2) -> Stream.concat(list1.stream(), list2.stream()) + .collect(Collectors.toList()))); // В 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 ((mapPair, pair) -> { + mapPair.getKeyById().merge(pair.getKey().getId(), pair.getKey(), (k1, k2) -> k1); + mapPair.getValueById() + .computeIfAbsent(pair.getValue().getKeyId(), s -> new ArrayList()) + .add(pair.getValue()); + }); + } + + @Override + public BinaryOperator combiner() { + return (m1, m2) -> { + BinaryOperator> keyMapMerge = mapMerger( + (Key k1, Key k2) -> k1 + ); + + Map keyMap = keyMapMerge.apply( + m1.getKeyById(), + m2.getKeyById() + ); + + BinaryOperator>> valueMapMerge = mapMerger( + (List list1, List list2) -> { + list1.addAll(list2); + return list1; + } + ); + + Map> valueMap = valueMapMerge.apply( + m1.getValueById(), + m2.getValueById() + ); + + return new MapPair(keyMap, valueMap); + }; + } + + @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> valueMap2 = res2.getValueById(); + + final Map> keyValuesMap2 = valueMap2.entrySet().stream() + .collect(Collectors.toMap(entry -> keyMap2.get(entry.getKey()), + Map.Entry::getValue, (val1, val2) -> { + val1.addAll(val2); + return val1; + })); + + Assert.assertEquals(keyValuesMap1, keyValuesMap2); + + final Map expectedKeys = new HashMap<>(); + final Map> expectedValues = new HashMap<>(); + + for (Pair p : pairs) { + expectedKeys.put(p.getKey().getId(), p.getKey()); + expectedValues.merge(p.getValue().getKeyId(), new ArrayList<>(singletonList(p.getValue())), + (s1, s2) -> { + s1.addAll(s2); + return s1; + } + ); + } + + final Map> expected = + expectedValues.entrySet().stream().collect(Collectors.toMap(entry -> keyMap2.get(entry.getKey()), + Map.Entry::getValue, (values1, values2) -> { + values1.addAll(values2); + return values1; + })); + + Assert.assertEquals(keyValuesMap1,expected); } } diff --git a/src/test/java/part3/exercise/lambda/LambdaExercise.java b/src/test/java/part3/exercise/lambda/LambdaExercise.java index 752e1f2..295f9d2 100755 --- a/src/test/java/part3/exercise/lambda/LambdaExercise.java +++ b/src/test/java/part3/exercise/lambda/LambdaExercise.java @@ -15,19 +15,21 @@ 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 = () -> new Person("John", "Galt", 30); assertEquals(person, getPerson.get()); } @Test public void function() { - final Function getPersonName1 = null; // TODO get the name of person using expression lambda + final Function getPersonName1 = person -> person.getFirstName(); - final Function getPersonName2 = null; // TODO get the name of person using method reference + final Function getPersonName2 = Person::getFirstName; - // TODO get the name of person and log it to System.out using statement lambda: {} - final Function getPersonNameAndLogIt = null; + final Function getPersonNameAndLogIt = person -> { + System.out.println(person.getFirstName()); + return person.getFirstName(); + }; final Person person = new Person("John", "Galt", 30); @@ -38,19 +40,17 @@ public void function() { @Test public void combineFunctions() { - final Function getPersonName = null; // TODO get the name of person + final Function getPersonName = Person::getFirstName; assertEquals("John", getPersonName.apply(new Person("John", "Galt", 30))); - final Function getStringLength = null; // TODO get string length + final Function getStringLength = 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 = person -> getStringLength.apply(getPersonName.apply(person)); - // 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); @@ -68,22 +68,20 @@ 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); assertEquals(new Person("John", "Galt", 66), person); - final Function getPersonName = null; // TODO + final Function getPersonName = Person::getFirstName; assertEquals("John", getPersonName.apply(person)); - final Predicate isJohnString = null; // TODO using method reference check that "John" equals string parameter + final Predicate isJohnString = "John"::equals; 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..47bd5de 100755 --- a/src/test/java/part3/exercise/stream/StreamsExercise.java +++ b/src/test/java/part3/exercise/stream/StreamsExercise.java @@ -8,8 +8,12 @@ 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.stream.Collectors; +import java.util.stream.Stream; import static org.junit.Assert.assertEquals; @@ -19,7 +23,9 @@ 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(Collectors.toList()); assertEquals(22, jobHistoryEntries.size()); } @@ -29,7 +35,10 @@ 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); } @@ -64,16 +73,27 @@ public String toString() { public void indexPersonsByEmployer1() { final List employees = getEmployees(); - final Map> index = null; // TODO + final Map> index = employees.stream() + .flatMap(StreamsExercise::employeesByPerson) + .collect(Collectors.groupingBy(PersonEmployer::getEmployer)); assertEquals(11, index.get("epam").size()); } + private static Stream employeesByPerson(Employee employee){ + return employee.getJobHistory().stream() + .map(jobHistoryEntry -> new PersonEmployer(employee.getPerson(), jobHistoryEntry.getEmployer())); + } + @Test public void indexPersonsByEmployer2() { final List employees = getEmployees(); - final Map> index = null; // TODO + final Map> index = employees.stream() + .flatMap(StreamsExercise::employeesByPerson) + .collect(Collectors.groupingBy(PersonEmployer::getEmployer, Collectors.mapping( + PersonEmployer::getPerson, Collectors.toList() + ))); assertEquals(11, index.get("epam").size()); } @@ -105,8 +125,10 @@ public String 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 @@ -114,7 +136,8 @@ 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, employee -> sumAllPersonDurations(employee).getDuration())); assertEquals(Integer.valueOf(8), personDuration.get(new Person("John", "Doe", 24))); } @@ -138,15 +161,19 @@ public Map getDurationByPositionIndex() { } private static PersonPositionIndex getPersonPositionIndex(Employee e) { - // TODO - throw new UnsupportedOperationException(); + Map map = e.getJobHistory().stream() + .collect(Collectors.toMap(JobHistoryEntry::getPosition, JobHistoryEntry::getDuration, + (d1, d2) -> d1 + d2)); + return new PersonPositionIndex(e.getPerson(), map); } @Test public void getSumDurationsForPersonByPosition() { final List employees = getEmployees(); - final List personIndexes = null; // TODO use getPersonPositionIndex + final List personIndexes = employees.stream() + .map(employee -> getPersonPositionIndex(employee)) + .collect(Collectors.toList()); assertEquals(1, personIndexes.get(3).getDurationByPositionIndex().size()); } @@ -175,11 +202,21 @@ public int getDuration() { } } + private Stream personPositionDuration(Employee employee){ + Map map = employee.getJobHistory().stream() + .collect(Collectors.toMap(JobHistoryEntry::getPosition, JobHistoryEntry::getDuration, + (d1, d2) -> d1 + d2)); + return map.keySet().stream() + .map(s -> new PersonPositionDuration(employee.getPerson(), s, map.get(s))); + } + @Test public void getDurationsForEachPersonByPosition() { final List employees = getEmployees(); - final List personPositionDurations = null; // TODO + final List personPositionDurations = employees.stream() + .flatMap(employee -> personPositionDuration(employee)) + .collect(Collectors.toList()); assertEquals(17, personPositionDurations.size()); @@ -190,7 +227,14 @@ 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(e -> personPositionDuration(e)) + .collect(Collectors.groupingBy( + PersonPositionDuration::getPosition, + Collectors + .collectingAndThen(Collectors.maxBy(Comparator.comparing(PersonPositionDuration::getDuration)), + Optional::get))); assertEquals(new Person("John", "White", 22), coolestPersonByPosition.get("QA").getPerson()); @@ -201,7 +245,14 @@ 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(e -> personPositionDuration(e)) + .collect(Collectors.groupingBy( + PersonPositionDuration::getPosition, + Collectors + .collectingAndThen(Collectors.maxBy(Comparator.comparing(PersonPositionDuration::getDuration)), + p -> p.get().getPerson()))); assertEquals(new Person("John", "White", 22), coolestPersonByPosition.get("QA"));