Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
18 changes: 15 additions & 3 deletions src/test/java/part2/exercise/CollectorsExercise2.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,15 +131,15 @@ public Map<String, List<Key>> getKnownKeys() {
}
}

private static class MapPair {
public static class MapPair {
private final Map<String, Key> keyById;
private final Map<String, List<Value>> valueById;

public MapPair() {
this(new HashMap<>(), new HashMap<>());
}

public MapPair(Map<String, Key> keyById, Map<String, List<Value>> valueById) {
MapPair(Map<String, Key> keyById, Map<String, List<Value>> valueById) {
this.keyById = keyById;
this.valueById = valueById;
}
Expand All @@ -151,9 +151,21 @@ public Map<String, Key> getKeyById() {
public Map<String, List<Value>> getValueById() {
return valueById;
}

public void put(Pair p) {
keyById.put(p.getKey().getId(), p.getKey());
final ArrayList<Value> value = new ArrayList<>();
value.add(p.getValue());
valueById.merge(p.getValue().getKeyId(),
value,
(l1, l2) -> {
l1.addAll(l2);
return l1;
});
}
}

private static <K, V, M extends Map<K, V>>
public static <K, V, M extends Map<K, V>>
BinaryOperator<M> mapMerger(BinaryOperator<V> mergeFunction) {
return (m1, m2) -> {
for (Map.Entry<K, V> e : m2.entrySet()) {
Expand Down
128 changes: 114 additions & 14 deletions src/test/java/part3/exercise/CollectorCombination.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
import part2.exercise.CollectorsExercise2.Key;
import part2.exercise.CollectorsExercise2.Value;

import java.util.List;
import java.util.Map;
import java.util.*;
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 static java.util.stream.Collectors.*;
import static org.junit.Assert.assertEquals;

public class CollectorCombination {

Expand All @@ -30,35 +33,132 @@ public A getA() {
public B getB() {
return b;
}

@Override
public String toString() {
return String.format("Pair<%s & %s>", a, b);
}
}

private static <T, M1, M2, R1, R2> Collector<T, Pair<M1, M2>, Pair<R1, R2>> paired(Collector<T, M1, R1> c1,
Collector<T, M2, R2> c2) {
// TODO
throw new UnsupportedOperationException();
return new Collector<T, Pair<M1, M2>, Pair<R1, R2>>() {
@Override
public Supplier<Pair<M1, M2>> supplier() {
return () -> new Pair<>(c1.supplier().get(), c2.supplier().get());
}

@Override
public BiConsumer<Pair<M1, M2>, T> accumulator() {
return (pair, t) -> {
c1.accumulator().accept(pair.getA(), t);
c2.accumulator().accept(pair.getB(), t);
};
}

@Override
public BinaryOperator<Pair<M1, M2>> combiner() {
return (p1, p2) -> new Pair<> (
c1.combiner().apply(p1.getA(), p2.getA()),
c2.combiner().apply(p1.getB(), p2.getB()));
}

@Override
public Function<Pair<M1, M2>, Pair<R1, R2>> finisher() {
return p -> new Pair<> (
c1.finisher().apply(p.getA()),
c2.finisher().apply(p.getB()));
}

@Override
public Set<Characteristics> characteristics() {
Set<Characteristics> set = new HashSet<>();
set.addAll(c1.characteristics());
set.addAll(c2.characteristics());
return set;
}
};
}

@Test
public void collectKeyValueMap() {
final List<CollectorsExercise2.Pair> pairs = CollectorsExercise2.generatePairs(10, 100);

// TODO see CollectorsExercise1::collectKeyValueMap
// В 1 проход в 2 Map с использованием MapPair и mapMerger
// final MapPair res2 = pairs.stream()
// .collect(new Collector<Pair, MapPair, MapPair>() {
final Map<Key, List<Value>> res1 = pairs.stream()
.collect(collectingAndThen(
new Collector<CollectorsExercise2.Pair, CollectorsExercise2.MapPair, CollectorsExercise2.MapPair>() {
@Override
public Supplier<CollectorsExercise2.MapPair> supplier() {
// TODO
return CollectorsExercise2.MapPair::new;
}

// Перепишите решение в слещующем виде:
final List<CollectorsExercise2.Pair> pairs = CollectorsExercise2.generatePairs(10, 100);
@Override
public BiConsumer<CollectorsExercise2.MapPair, CollectorsExercise2.Pair> accumulator() {
// TODO
return CollectorsExercise2.MapPair::put;
}

@Override
public BinaryOperator<CollectorsExercise2.MapPair> combiner() {
// TODO
return (mapPair, mapPair2) -> {
BinaryOperator<Map<String, Key>> keyMerger = CollectorsExercise2.mapMerger((v1, v2) -> v1);
keyMerger.apply(mapPair.getKeyById(), mapPair2.getKeyById());
BinaryOperator<Map<String, List<Value>>> valueMerger =
CollectorsExercise2.mapMerger((v1, v2) -> {
v1.addAll(v2);
return v1;
});
valueMerger.apply(mapPair.getValueById(), mapPair2.getValueById());
return mapPair;
};
}

@Override
public Function<CollectorsExercise2.MapPair, CollectorsExercise2.MapPair> finisher() {
return Function.identity();
}

@Override
public Set<Characteristics> characteristics() {
return Collections.unmodifiableSet(EnumSet.of(
Characteristics.UNORDERED,
Characteristics.IDENTITY_FINISH));
}
},
(CollectorsExercise2.MapPair mmp) -> mmp.getKeyById().entrySet().stream()
.map(kp -> new AbstractMap.SimpleEntry<>(kp.getValue(), mmp.getValueById().get(kp.getKey())))
.collect(toMap(
Map.Entry::getKey,
Map.Entry::getValue
))
)
);

final Pair<Map<String, Key>, Map<String, List<Value>>> res2 = pairs.stream()
// Перепишите решение в слещующем виде:
final Map<Key, List<Value>> res2 = pairs.stream()
.collect(
paired(
mapping(CollectorsExercise2.Pair::getKey, toMap(Key::getId, Function.identity(), (x, y) -> x)),
mapping(CollectorsExercise2.Pair::getValue, groupingBy(Value::getKeyId))
collectingAndThen(
paired(
mapping(CollectorsExercise2.Pair::getKey,
toMap(Key::getId, Function.identity(), (x, y) -> x)),
mapping(CollectorsExercise2.Pair::getValue,
groupingBy(Value::getKeyId))
),
mmp -> mmp.getA().entrySet().stream()
.map(kp -> new AbstractMap.SimpleEntry<>(kp.getValue(), mmp.getB().get(kp.getKey())))
.collect(toMap(
Map.Entry::getKey,
Map.Entry::getValue
))
)
);


// TODO tests
throw new UnsupportedOperationException();
assertEquals(res1, res2);
}

}
37 changes: 24 additions & 13 deletions src/test/java/part3/exercise/lambda/LambdaExercise.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,25 @@ public class LambdaExercise {
public void supply() {
final Person person = new Person("John", "Galt", 30);

final Supplier<Person> getPerson = null; // TODO return person from Supplier
final Supplier<Person> getPerson = () -> person; // TODO return person from Supplier

assertEquals(person, getPerson.get());
}

@Test
public void function() {
final Function<Person, String> getPersonName1 = null; // TODO get the name of person using expression lambda
// TODO get the name of person using expression lambda
final Function<Person, String> getPersonName1 =
p -> p.getFirstName();

final Function<Person, String> getPersonName2 = null; // TODO get the name of person using method reference
// TODO get the name of person using method reference
final Function<Person, String> getPersonName2 = Person::getFirstName;

// TODO get the name of person and log it to System.out using statement lambda: {}
final Function<Person, String> getPersonNameAndLogIt = null;
final Function<Person, String> getPersonNameAndLogIt = p -> {
System.out.println(p.getFirstName());
return p.getFirstName();
};

final Person person = new Person("John", "Galt", 30);

Expand All @@ -38,19 +44,20 @@ public void function() {

@Test
public void combineFunctions() {
final Function<Person, String> getPersonName = null; // TODO get the name of person
// TODO get the name of person
final Function<Person, String> getPersonName = Person::getFirstName;

assertEquals("John", getPersonName.apply(new Person("John", "Galt", 30)));

final Function<String, Integer> getStringLength = null; // TODO get string length
// TODO get string length
final Function<String, Integer> getStringLength = String::length;

assertEquals(Integer.valueOf(3), getStringLength.apply("ABC"));

// TODO get person name length using getPersonName and getStringLength without andThen
final Function<Person, Integer> getPersonNameLength1 = null;
final Function<Person, Integer> getPersonNameLength1 = p -> getStringLength.apply(getPersonName.apply(p));

// TODO get person name length using getPersonName and getStringLength with andThen
final Function<Person, Integer> getPersonNameLength2 = null;
final Function<Person, Integer> getPersonNameLength2 = getPersonName.andThen(getStringLength);

final Person person = new Person("John", "Galt", 30);

Expand All @@ -69,25 +76,29 @@ private Person createPerson(PersonFactory pf) {
// ((T -> R), (R -> boolean)) -> (T -> boolean)
private <T, R> Predicate<T> combine(Function<T, R> f, Predicate<R> p) {
// TODO
throw new UnsupportedOperationException();
return v -> p.test(f.apply(v));
}

@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<Person, String> getPersonName = null; // TODO
final Function<Person, String> getPersonName = Person::getFirstName; // TODO

assertEquals("John", getPersonName.apply(person));

final Predicate<String> isJohnString = null; // TODO using method reference check that "John" equals string parameter
// TODO using method reference check that "John" equals string parameter
final Predicate<String> isJohnString = LambdaExercise::isJohn;

final Predicate<Person> isJohnPerson = combine(getPersonName, isJohnString);

assertEquals(true, isJohnPerson.test(person));
}

private static boolean isJohn(String name) {
return name.equals("John");
}
}
Loading