Skip to content

Streams Part 3 (by Narek Karapetian) #82

New issue

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

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

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
7 changes: 2 additions & 5 deletions src/test/java/part2/exercise/CollectorsExercise2.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package part2.exercise;

import data.Employee;
import data.JobHistoryEntry;
import data.Person;
import org.junit.Test;

import java.util.*;
Expand Down Expand Up @@ -131,7 +128,7 @@ 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;

Expand All @@ -153,7 +150,7 @@ public Map<String, List<Value>> getValueById() {
}
}

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
124 changes: 115 additions & 9 deletions src/test/java/part3/exercise/CollectorCombination.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,22 @@
import org.junit.Test;
import part2.exercise.CollectorsExercise2;
import part2.exercise.CollectorsExercise2.Key;
import part2.exercise.CollectorsExercise2.MapPair;
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 java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toMap;
import static org.junit.Assert.assertEquals;
import static part2.exercise.CollectorsExercise2.generatePairs;
import static part2.exercise.CollectorsExercise2.mapMerger;

public class CollectorCombination {

Expand All @@ -34,8 +42,48 @@ public B getB() {

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 (m1M2Pair, t) -> {
c1.accumulator().accept(m1M2Pair.getA(), t);
c2.accumulator().accept(m1M2Pair.getB(), t);
};
}

@Override
public BinaryOperator<Pair<M1, M2>> combiner() {
return (m1M2Pair1, m1M2Pair2) -> {
M1 m1 = c1.combiner().apply(m1M2Pair1.getA(), m1M2Pair2.getA());
M2 m2 = c2.combiner().apply(m1M2Pair1.getB(), m1M2Pair2.getB());
return new Pair<>(m1, m2);
};
}

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

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

return ch;
}
};
}

@Test
Expand All @@ -44,10 +92,60 @@ public void collectKeyValueMap() {
// В 1 проход в 2 Map с использованием MapPair и mapMerger
// final MapPair res2 = pairs.stream()
// .collect(new Collector<Pair, MapPair, MapPair>() {
List<CollectorsExercise2.Pair> pairs = generatePairs(10, 100);

// Перепишите решение в слещующем виде:
final List<CollectorsExercise2.Pair> pairs = CollectorsExercise2.generatePairs(10, 100);
final MapPair res1 =
pairs.stream()
.collect(new Collector<CollectorsExercise2.Pair, MapPair, MapPair>() {
@Override
public Supplier<MapPair> supplier() {
return MapPair::new;
}

@Override
public BiConsumer<MapPair, CollectorsExercise2.Pair> accumulator() {
return (mapPair, pair) -> {
mapPair.getKeyById().putIfAbsent(pair.getKey().getId(), pair.getKey());
mapPair.getValueById().computeIfAbsent(pair.getValue().getKeyId(),
s -> new ArrayList<>()).add(pair.getValue());
};
}

@Override
public BinaryOperator<MapPair> combiner() {
return (mapPair1, mapPair2) -> {
BinaryOperator<Map<String, Key>> keyBinaryOperator = mapMerger((o, o2) -> o);
Map<String, Key> mapKeys =
keyBinaryOperator.apply(mapPair1.getKeyById(), mapPair2.getKeyById());

BinaryOperator<Map<String, List<Value>>> valueBinaryOperator =
mapMerger(
(list1, list2) -> {
list1.addAll(list2);
return list1;
});
Map<String, List<Value>> mapValues =
valueBinaryOperator.apply(mapPair1.getValueById(), mapPair2.getValueById());

return new MapPair(mapKeys, mapValues);
};
}

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

@Override
public Set<Characteristics> characteristics() {
return Collections.unmodifiableSet(EnumSet.of(
Characteristics.UNORDERED,
Collector.Characteristics.IDENTITY_FINISH));
}
});


// Перепишите решение в слещующем виде:
final Pair<Map<String, Key>, Map<String, List<Value>>> res2 = pairs.stream()
.collect(
paired(
Expand All @@ -56,9 +154,17 @@ public void collectKeyValueMap() {
)
);

res1.getKeyById().forEach((s, key) -> {
String k = res2.getA().get(s).getId();
assertEquals(s, k);
});

res1.getValueById().forEach((s, values) -> {
List<Value> values2 = res2.getB().get(s);
assertEquals(values.get(0), values2.get(0));
assertEquals(values.size(), values2.size());
});

// TODO tests
throw new UnsupportedOperationException();
}

}
32 changes: 20 additions & 12 deletions src/test/java/part3/exercise/lambda/LambdaExercise.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,23 @@ 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;

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

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

final Function<Person, String> getPersonName2 = null; // TODO get the name of person using method reference
final Function<Person, String> 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<Person, String> getPersonNameAndLogIt = null;
final Function<Person, String> getPersonNameAndLogIt = person -> {
String firstName = person.getFirstName();
System.out.println(firstName);
return firstName;
};

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

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

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

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

final Function<String, Integer> getStringLength = null; // TODO get string length
final Function<String, Integer> getStringLength = s -> s.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<Person, Integer> getPersonNameLength1 = null;
final Function<Person, Integer> getPersonNameLength1 =
person -> getStringLength.apply(getPersonName.apply(person));

// 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 +74,28 @@ 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 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<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
final Predicate<String> isJohnString = this::johnTest; // TODO using method reference check that "John" equals string parameter

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

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

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