Skip to content
Open
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
221 changes: 178 additions & 43 deletions src/test/java/lambda/part3/exercise/Mapping.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,7 @@
import data.Person;
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.function.BiConsumer;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
Expand All @@ -32,8 +28,10 @@ public List<T> getList() {
// [T] -> (T -> R) -> [R]
// [T1, T2, T3] -> (T -> R) -> [R1, R2, R3]
public <R> MapHelper<R> map(Function<T, R> f) {
// TODO
throw new UnsupportedOperationException();
final List<R> result = new ArrayList<>();
list.forEach(t ->
result.add(f.apply(t)));
return new MapHelper<>(result);
}

// [T] -> (T -> [R]) -> [R]
Expand Down Expand Up @@ -76,11 +74,9 @@ public void mapping() {

final List<Employee> mappedEmployees =
new MapHelper<>(employees)
/*
.map(TODO) // change name to John .map(e -> e.withPerson(e.getPerson().withFirstName("John")))
.map(TODO) // add 1 year to experience duration .map(e -> e.withJobHistory(addOneYear(e.getJobHistory())))
.map(TODO) // replace qa with QA
* */
.map(e -> e.withPerson(e.getPerson().withFirstName("John")))
.map(e -> e.withJobHistory(addOneYear(e.getJobHistory())))
.map(e -> e.withJobHistory(qaToUpperCase(e.getJobHistory())))
.getList();

final List<Employee> expectedResult =
Expand Down Expand Up @@ -108,64 +104,205 @@ public void mapping() {
assertEquals(mappedEmployees, expectedResult);
}

// [JobHistoryEntry] -> (JobHistoryEntry -> JobHistoryEntry) -> [JobHistoryEntry]
private static List<JobHistoryEntry> qaToUpperCase(List<JobHistoryEntry> list) {
return new MapHelper<>(list)
.map(entry ->
entry.getPosition().equals("qa") ? entry.withPosition("QA") : entry)
.getList();
}

// [JobHistoryEntry] -> (JobHistoryEntry -> JobHistoryEntry) -> [JobHistoryEntry]
private static List<JobHistoryEntry> addOneYear(List<JobHistoryEntry> list) {
return new MapHelper<>(list)
.map(entry ->
entry.withDuration(entry.getDuration() + 1))
.getList();
}

private static class LazyMapHelper<T, R> {

public LazyMapHelper(List<T> list, Function<T, R> function) {
private final List<T> list;
private final Function<T, R> function;

private LazyMapHelper(List<T> list, Function<T, R> function) {
this.list = list;
this.function = function;
}

public static <T> LazyMapHelper<T, T> from(List<T> list) {
return new LazyMapHelper<>(list, Function.identity());
}

public List<R> force() {
// TODO
throw new UnsupportedOperationException();
return new MapHelper<>(list).map(function).getList();
}

public <R2> LazyMapHelper<T, R2> map(Function<R, R2> f) {
// TODO
throw new UnsupportedOperationException();
Function<T, R2> newFunction = function.andThen(f);
return new LazyMapHelper<>(list, newFunction);
}

}

private static class LazyFlatMapHelper<T, R> {
interface ReachIterable<T> {
//hasNext and next
boolean tryGet(Consumer<T> c);


public LazyFlatMapHelper(List<T> list, Function<T, List<R>> function) {
//TODO boolean anyMatch(Predicate<T> p)
default boolean anyMatch(Predicate<T> p) {
return firstMatch(p).isPresent();
}

public static <T> LazyFlatMapHelper<T, T> from(List<T> list) {
throw new UnsupportedOperationException();
//TODO boolean allMatch(Predicate<T> p)
default boolean allMatch(Predicate<T> p) {
final List<Boolean> allMatch = Collections.singletonList(true);
final List<Boolean> keep = Collections.singletonList(true);
Consumer<T> consumer = t -> {
if (keep.get(0) && !p.test(t)) {
allMatch.set(0, false);
keep.set(0, false);
}
};
while (tryGet(consumer)) {}
return allMatch.get(0);
}

public List<R> force() {
// TODO
throw new UnsupportedOperationException();
//TODO boolean noneMatch(Predicate<T> p)
default boolean noneMatch(Predicate<T> p) {
return !allMatch(p);
}

// TODO filter
// (T -> boolean) -> (T -> [T])
// filter: [T1, T2] -> (T -> boolean) -> [T2]
// flatMap": [T1, T2] -> (T -> [T]) -> [T2]
//TODO Optional<T> firstMatch(Predicate<T> p)
default Optional<T> firstMatch(Predicate<T> p) {
final List<Optional<T>> optionals = Collections.singletonList(Optional.empty());
final List<Boolean> keep = Collections.singletonList(true);
Consumer<T> consumer = t -> {
if (keep.get(0) && p.test(t)) {
optionals.set(0, Optional.ofNullable(t));
keep.set(0, false);
}
};
while (tryGet(consumer)) {}
return optionals.get(0);
}

static <T> ReachIterable<T> from(List<T> list) {
return new ReachIterable<T>() {
@Override
public boolean tryGet(Consumer<T> c) {
Iterator<T> iterator = list.iterator();
if (iterator.hasNext()) {
c.accept(iterator.next());
return true;
}
return false;
}
};
}
}

public <R2> LazyFlatMapHelper<T, R2> map(Function<R, R2> f) {
final Function<R, List<R2>> listFunction = rR2TorListR2(f);
return flatMap(listFunction);
interface Traversable<T> {
void forEach(Consumer<T> c);

default Traversable<T> filter(Predicate<T> p) {
final Traversable<T> self = this;
return new Traversable<T>() {
@Override
public void forEach(Consumer<T> c) {
self.forEach(t -> {
if (p.test(t))
c.accept(t);
});
}
};
}

// (R -> R2) -> (R -> [R2])
private <R2> Function<R, List<R2>> rR2TorListR2(Function<R, R2> f) {
throw new UnsupportedOperationException();
default <R> Traversable<R> flatMap(Function<T, List<R>> f) {
final Traversable<T> self = this;
return new Traversable<R>() {
@Override
public void forEach(Consumer<R> c) {
self.forEach(
t -> f.apply(t)
.forEach(c));
}
};
}

// TODO *
public <R2> LazyFlatMapHelper<T, R2> flatMap(Function<R, List<R2>> f) {
throw new UnsupportedOperationException();
default <R> Traversable<R> map(Function<T, R> f) {
final Traversable<T> self = this;
return new Traversable<R>() {
@Override
public void forEach(Consumer<R> c) {
self.forEach(t -> c.accept(f.apply(t)));
}
};
}

default List<T> toList() {
final List<T> list = new ArrayList<>();
forEach(list::add);
return list;
}

static <T> Traversable<T> from(List<T> list) {
return new Traversable<T>() {
@Override
public void forEach(Consumer<T> c) {
list.forEach(c);
}
};
}
}

@Test
public void testFlatMap() {
final List<Employee> employees =
Arrays.asList(
new Employee(
new Person("a", "Galt", 30),
Arrays.asList(
new JobHistoryEntry(2, "dev", "epam"),
new JobHistoryEntry(1, "dev", "google")
)),
new Employee(
new Person("b", "Doe", 40),
Arrays.asList(
new JobHistoryEntry(3, "qa", "yandex"),
new JobHistoryEntry(1, "qa", "epam"),
new JobHistoryEntry(1, "dev", "abc")
))
);

System.err.println(
Arrays.toString(
Traversable.from(employees).flatMap(Employee::getJobHistory).toList().toArray()));
}

@Test
public void testFilter() {
final List<Employee> employees =
Arrays.asList(
new Employee(
new Person("a", "Galt", 30),
Arrays.asList(
new JobHistoryEntry(2, "dev", "epam"),
new JobHistoryEntry(1, "dev", "google")
)),
new Employee(
new Person("b", "Doe", 40),
Arrays.asList(
new JobHistoryEntry(3, "qa", "yandex"),
new JobHistoryEntry(1, "qa", "epam"),
new JobHistoryEntry(1, "dev", "abc")
))
);

System.err.println(
Arrays.toString(
Traversable.from(employees).filter(e -> e.getPerson().getFirstName().equals("a")).toList().toArray()));
}

@Test
public void lazy_mapping() {
Expand Down Expand Up @@ -193,11 +330,9 @@ public void lazy_mapping() {

final List<Employee> mappedEmployees =
LazyMapHelper.from(employees)
/*
.map(TODO) // change name to John
.map(TODO) // add 1 year to experience duration
.map(TODO) // replace qa with QA
* */
.map(e -> e.withPerson(e.getPerson().withFirstName("John"))) // change name to John
.map(e -> e.withJobHistory(addOneYear(e.getJobHistory()))) // add 1 year to experience duration
.map(e -> e.withJobHistory(qaToUpperCase(e.getJobHistory()))) // replace qa with QA
.force();

final List<Employee> expectedResult =
Expand Down