diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..9a874b5 Binary files /dev/null and b/.DS_Store differ diff --git a/src/.DS_Store b/src/.DS_Store new file mode 100644 index 0000000..ca5d0e6 Binary files /dev/null and b/src/.DS_Store differ diff --git a/src/test/.DS_Store b/src/test/.DS_Store new file mode 100644 index 0000000..55c1fcb Binary files /dev/null and b/src/test/.DS_Store differ diff --git a/src/test/java/.DS_Store b/src/test/java/.DS_Store new file mode 100644 index 0000000..d58fbcc Binary files /dev/null and b/src/test/java/.DS_Store differ diff --git a/src/test/java/part2/.DS_Store b/src/test/java/part2/.DS_Store new file mode 100644 index 0000000..f212fe4 Binary files /dev/null and b/src/test/java/part2/.DS_Store differ diff --git a/src/test/java/part2/exercise/CollectorsExercise1.java b/src/test/java/part2/exercise/CollectorsExercise1.java index 46b6765..ff79169 100755 --- a/src/test/java/part2/exercise/CollectorsExercise1.java +++ b/src/test/java/part2/exercise/CollectorsExercise1.java @@ -6,17 +6,12 @@ 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.stream.Collectors.*; public class CollectorsExercise1 { @@ -51,18 +46,46 @@ public int getDuration() { } } + public Stream convert(Employee employee) { + return employee.getJobHistory().stream() + .map(j -> new PersonPositionDuration(employee.getPerson(), j.getPosition(), j.getDuration())); + } + + public Stream convertToSum(final Employee employee) { + return employee.getJobHistory() + .stream() + .collect( + groupingBy( + JobHistoryEntry::getPosition, + collectingAndThen(Collectors.summarizingInt(JobHistoryEntry::getDuration), IntSummaryStatistics::getSum) + )) + .entrySet() + .stream() + .map((k) -> new PersonPositionDuration(employee.getPerson(), k.getKey(), k.getValue().intValue())); + } + // With the longest duration on single job private Map getCoolestByPosition(List employees) { - // First option - // Collectors.maxBy - // Collectors.collectingAndThen - // Collectors.groupingBy - - // Second option - // Collectors.toMap - // iterate twice: stream...collect(...).stream()... - // TODO - throw new UnsupportedOperationException(); + final Map collect = employees + .stream() + .flatMap(this::convert) + .collect(groupingBy(PersonPositionDuration::getPosition, + collectingAndThen(Collectors.maxBy(Comparator.comparingInt(PersonPositionDuration::getDuration)), + e -> e.map(PersonPositionDuration::getPerson).get()))); + + final Map collect1 = employees + .stream() + .flatMap(this::convert) + .collect( + toMap( + PersonPositionDuration::getPosition, + Function.identity(), + BinaryOperator.maxBy(Comparator.comparingInt(PersonPositionDuration::getDuration)) + )) + .entrySet() + .stream() + .collect(toMap(Map.Entry::getKey, e -> e.getValue().getPerson())); + return collect; } @Test @@ -75,8 +98,15 @@ public void getTheCoolestOne2() { // 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 employees + .stream() + .flatMap(this::convertToSum) + .collect(groupingBy + (PersonPositionDuration::getPosition, + collectingAndThen(Collectors.maxBy(Comparator.comparingInt(PersonPositionDuration::getDuration)), + e -> e.map(PersonPositionDuration::getPerson).get() + ) + )); } private List getEmployees() { diff --git a/src/test/java/part2/exercise/CollectorsExercise2.java b/src/test/java/part2/exercise/CollectorsExercise2.java index 00fda00..4ede17c 100755 --- a/src/test/java/part2/exercise/CollectorsExercise2.java +++ b/src/test/java/part2/exercise/CollectorsExercise2.java @@ -1,8 +1,5 @@ package part2.exercise; -import data.Employee; -import data.JobHistoryEntry; -import data.Person; import org.junit.Test; import java.util.*; @@ -16,14 +13,17 @@ import java.util.stream.IntStream; import java.util.stream.Stream; +import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toList; +import static java.util.stream.Collectors.toMap; +import static org.junit.Assert.assertEquals; public class CollectorsExercise2 { private static String generateString() { - final String letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - final int maxLength = 10; - final int length = ThreadLocalRandom.current().nextInt(maxLength) + 1; + final String letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + final int maxLength = 10; + final int length = ThreadLocalRandom.current().nextInt(maxLength) + 1; return IntStream.range(0, length) .mapToObj(letters::charAt) @@ -31,20 +31,20 @@ private static String generateString() { .collect(Collectors.joining()); } - private static String[] generateStringArray(int length) { + private static String[] generateStringArray(final int length) { return Stream.generate(CollectorsExercise2::generateString) .limit(length) .toArray(String[]::new); } - public static String pickString(String[] array) { + public static String pickString(final String[] array) { return array[ThreadLocalRandom.current().nextInt(array.length)]; } public static class Key { private final String id; - public Key(String id) { + public Key(final String id) { this.id = id; } @@ -72,7 +72,7 @@ public int hashCode() { public static class Value { private final String keyId; - public Value(String keyId) { + public Value(final String keyId) { this.keyId = keyId; } @@ -85,7 +85,7 @@ public static class Pair { private final Key key; private final Value value; - public Pair(Key key, Value value) { + public Pair(final Key key, final Value value) { this.key = key; this.value = value; } @@ -99,7 +99,7 @@ public Value getValue() { } } - public static List generatePairs(int idCount, int length) { + public static List generatePairs(final int idCount, final int length) { final String[] ids = generateStringArray(idCount); return Stream.generate(() -> new Pair(new Key(pickString(ids)), new Value(pickString(ids)))) @@ -112,7 +112,13 @@ private static class SubResult { private final Map> knownKeys; private final Map> valuesWithoutKeys; - public SubResult(Map> subResult, Map> knownKeys, Map> valuesWithoutKeys) { + public SubResult() { + this(new HashMap<>(), new HashMap<>(), new HashMap<>()); + } + + public SubResult(final Map> subResult, + final Map> knownKeys, + final Map> valuesWithoutKeys) { this.subResult = subResult; this.knownKeys = knownKeys; this.valuesWithoutKeys = valuesWithoutKeys; @@ -139,7 +145,8 @@ public MapPair() { this(new HashMap<>(), new HashMap<>()); } - public MapPair(Map keyById, Map> valueById) { + + public MapPair(final Map keyById, final Map> valueById) { this.keyById = keyById; this.valueById = valueById; } @@ -154,7 +161,7 @@ public Map> getValueById() { } private static > - BinaryOperator mapMerger(BinaryOperator mergeFunction) { + BinaryOperator mapMerger(final BinaryOperator mergeFunction) { return (m1, m2) -> { for (Map.Entry e : m2.entrySet()) { m1.merge(e.getKey(), e.getValue(), mergeFunction); @@ -168,32 +175,51 @@ public void collectKeyValueMap() { final List pairs = generatePairs(10, 100); // В два прохода - // final Map keyMap1 = pairs.stream()... + final Map keyMap1 = pairs + .stream() + .map(Pair::getKey) + .collect(toMap(Key::getId, Function.identity(), (a, b) -> a)); - // final Map> valuesMap1 = pairs.stream()... + final Map> valueMap1 = pairs + .stream() + .map(Pair::getValue) + .collect(groupingBy(Value::getKeyId)); // В каждом Map.Entry id ключа должно совпадать с keyId для каждого значения в списке - // final Map> keyValuesMap1 = valueMap1.entrySet().stream()... + final Map> keyValuesMap1 = valueMap1 + .entrySet() + .stream() + .collect(toMap(e -> keyMap1.get(e.getKey()), Map.Entry::getValue)); // В 1 проход в 2 Map с использованием MapPair и mapMerger final MapPair res2 = pairs.stream() .collect(new Collector() { @Override public Supplier supplier() { - // TODO - throw new UnsupportedOperationException(); + return MapPair::new; } @Override public BiConsumer accumulator() { - // TODO add key and value to maps - throw new UnsupportedOperationException(); + return (mp, p) -> { + mp.getKeyById().put(p.getKey().getId(), p.getKey()); + mp.getValueById().computeIfAbsent(p.getValue().getKeyId(), v -> new ArrayList<>()).add(p.getValue()); + }; } @Override public BinaryOperator combiner() { - // TODO use mapMerger - throw new UnsupportedOperationException(); + return (p1, p2) -> { + final BinaryOperator> mapBinaryOperator = mapMerger((a, b) -> a); + final BinaryOperator>> mapBinaryOperator1 = mapMerger((a, b) -> { + a.addAll(b); + return a; + }); + final Map apply = mapBinaryOperator.apply(p1.getKeyById(), p2.getKeyById()); + final Map> apply1 = mapBinaryOperator1.apply(p1.getValueById(), p2.getValueById()); + return new MapPair(apply, apply1); + + }; } @Override @@ -209,49 +235,14 @@ public Set characteristics() { } }); - final Map keyMap2 = res2.getKeyById(); + 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(); + final Map> keyValuesMap2 = valuesMap2 + .entrySet() + .stream() + .collect(toMap(e -> keyMap2.get(e.getKey()), Map.Entry::getValue)); - // compare results + assertEquals(keyValuesMap1, keyValuesMap2); } - }