Skip to content
This repository was archived by the owner on Feb 10, 2021. It is now read-only.

Exercise/completed #2

Open
wants to merge 27 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6d57b66
Exercise completed
May 5, 2018
b8fd66e
Merge branch 'master' into exercise/completed
tboychuk Jul 17, 2018
9059a3c
Complete task
tboychuk Jul 17, 2018
5488706
Merge branch 'master' into exercise/completed
tboychuk Jul 17, 2018
f42e1e8
Update form master
tboychuk Jul 17, 2018
d66e448
Add Sum of Squares exercise
tboychuk Jul 18, 2018
2c22e72
Merge branch 'master' into exercise/completed
tboychuk Jul 18, 2018
8ba44af
Complete the exercise
tboychuk Jul 18, 2018
ea54727
Merge branch 'master' into exercise/completed
tboychuk Jul 19, 2018
3aa059f
Merge branch 'master' into exercise/completed
tboychuk Aug 9, 2018
8e2c8b7
Complete the exercise CrazyLambdas.java
tboychuk Aug 9, 2018
d5b89fc
Merge branch 'master' into exercise/completed
tboychuk Aug 9, 2018
de0d56a
Merge branch 'master' into exercise/completed
tboychuk Aug 10, 2018
429e5e6
Complete the exercise CrazyLambdas.java
tboychuk Aug 10, 2018
ae3d67c
Merge branch 'master' into exercise/completed
tboychuk Aug 13, 2018
691adf0
Complete AccountAnalytics.java exercise
tboychuk Aug 13, 2018
fdfb50a
Merge branch 'master' into exercise/completed
tboychuk Aug 13, 2018
d5a4c0c
Merge branch 'master' into exercise/completed
tboychuk Oct 22, 2018
9aa98d0
Merge branch 'master' into exercise/completed
tboychuk Nov 1, 2018
56ab37b
Merge branch 'master' into exercise/completed
tboychuk Nov 7, 2018
0a7dd78
Add impl for new method of AccountAnalytics.java
tboychuk Nov 7, 2018
1598f60
Merge branch 'master' into exercise/completed
tboychuk Dec 16, 2018
9e8112f
Implement new methods in AccountAnalytics.java
tboychuk Dec 16, 2018
b9baf56
Merge branch 'master' into exercise/completed
tboychuk Dec 16, 2018
cad70b9
Implement new methods in AccountAnalytics.java
tboychuk Dec 16, 2018
9e7c40e
Merge branch 'master' into exercise/completed
tboychuk Jul 1, 2019
3d8c9c9
Complete new tasks in CrazyLambdas.java
tboychuk Jul 1, 2019
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
75 changes: 59 additions & 16 deletions account-analytics/src/main/java/com.bobocode/AccountAnalytics.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,17 @@

import com.bobocode.exception.EntityNotFoundException;
import com.bobocode.model.Account;
import com.bobocode.model.Sex;

import java.math.BigDecimal;
import java.time.Month;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Stream;

import static java.util.Comparator.comparing;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.*;

import static java.util.stream.Collectors.mapping;
import static java.util.stream.Collectors.toMap;
Expand All @@ -30,7 +37,8 @@ private AccountAnalytics(Collection<Account> accounts) {
* @return account with max balance wrapped with optional
*/
public Optional<Account> findRichestPerson() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return accounts.stream()
.max(comparing(Account::getBalance));
}

/**
Expand All @@ -40,7 +48,9 @@ public Optional<Account> findRichestPerson() {
* @return a list of accounts
*/
public List<Account> findAccountsByBirthdayMonth(Month birthdayMonth) {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return accounts.stream()
.filter(a -> a.getBirthday().getMonth().equals(birthdayMonth))
.collect(toList());
}

/**
Expand All @@ -50,7 +60,8 @@ public List<Account> findAccountsByBirthdayMonth(Month birthdayMonth) {
* @return a map where key is true or false, and value is list of male, and female accounts
*/
public Map<Boolean, List<Account>> partitionMaleAccounts() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return accounts.stream()
.collect(partitioningBy(a -> a.getSex().equals(Sex.MALE)));
Copy link

@omgkanamikun omgkanamikun Aug 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

В мене в IDE метод .collect(partition____) не розпізнає за замовчуванням, та не знаходить параметри,
геттери в Account додавав.
Запрацювало після статік імпорта, але це як підножка при написанні, вчора теж на цьому завис.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can start by typing Collectors. and it will show you all available methods like partitionBy()

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Account class is mapped with lombok annotations. So it requires to enable annotation processing in your IDE + lombok plugin

}

/**
Expand All @@ -60,7 +71,8 @@ public Map<Boolean, List<Account>> partitionMaleAccounts() {
* @return a map where key is an email domain and value is a list of all account with such email
*/
public Map<String, List<Account>> groupAccountsByEmailDomain() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return accounts.stream()
.collect(groupingBy(a -> a.getEmail().split("@")[1]));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

що значить [1]?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It means, that after splitting email by string @ you will have an array String[]. The first element of that array will contain a username, and the second will contain email domain name.

E.g. "omgkanamikun@gmail.com".split("@") will result in array ["omgkanamikun", "gmail.com"]. So to get a domain name, you need to get an element from array by index 1.

}

/**
Expand All @@ -69,7 +81,9 @@ public Map<String, List<Account>> groupAccountsByEmailDomain() {
* @return total number of letters of first and last names of all accounts
*/
public int getNumOfLettersInFirstAndLastNames() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return accounts.stream()
.mapToInt(a -> a.getFirstName().length() + a.getLastName().length())
.sum();
}

/**
Expand All @@ -78,7 +92,9 @@ public int getNumOfLettersInFirstAndLastNames() {
* @return total balance of all accounts
*/
public BigDecimal calculateTotalBalance() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return accounts.stream()
.map(Account::getBalance)
.reduce(BigDecimal.ZERO, BigDecimal::add);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you use ZERO after "BigDecimal" ? It's something about method reduce?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method reduce is overloaded. So you have two options:

  • Optional<T> reduce(BinaryOperator<T> accumulator);
  • T reduce(T identity, BinaryOperator<T> accumulator);

I used the second one, that has an identity (initial) value, because I wanted to receive real value rather than optional

}

/**
Expand All @@ -87,7 +103,10 @@ public BigDecimal calculateTotalBalance() {
* @return list of accounts sorted by first and last names
*/
public List<Account> sortByFirstAndLastNames() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return accounts.stream()
.sorted(comparing(Account::getFirstName)
.thenComparing(Account::getLastName))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Почему здесь не получается использовать лямбду а нужно обязательно использовать methodReference? Не дает сделать Идея лямбду.

.collect(toList());
}

/**
Expand All @@ -97,7 +116,9 @@ public List<Account> sortByFirstAndLastNames() {
* @return true if there is an account that has an email with provided domain
*/
public boolean containsAccountWithEmailDomain(String emailDomain) {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return accounts.stream()
.map(Account::getEmail)
.anyMatch(email -> email.split("@")[1].equals(emailDomain));
}

/**
Expand All @@ -108,7 +129,11 @@ public boolean containsAccountWithEmailDomain(String emailDomain) {
* @return account balance
*/
public BigDecimal getBalanceByEmail(String email) {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return accounts.stream()
.filter(account -> account.getEmail().equals(email))
.findFirst()
.map(Account::getBalance)
.orElseThrow(() -> new EntityNotFoundException(String.format("Cannot find Account by email=%s", email)));
}

/**
Expand All @@ -117,7 +142,8 @@ public BigDecimal getBalanceByEmail(String email) {
* @return map of accounts by its ids
*/
public Map<Long, Account> collectAccountsById() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return accounts.stream()
.collect(toMap(Account::getId, identity()));
}

/**
Expand All @@ -128,7 +154,9 @@ public Map<Long, Account> collectAccountsById() {
* @return map of account by its ids the were created in a particular year
*/
public Map<String, BigDecimal> collectBalancesByIdForAccountsCreatedOn(int year) {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return accounts.stream()
.filter(account -> account.getCreationDate().getYear() == year)
.collect(toMap(Account::getEmail, Account::getBalance));
}

/**
Expand All @@ -138,7 +166,8 @@ public Map<String, BigDecimal> collectBalancesByIdForAccountsCreatedOn(int year)
* @return a map where key is a last name and value is a set of first names
*/
public Map<String, Set<String>> groupFirstNamesByLastNames() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return accounts.stream()
.collect(groupingBy(Account::getLastName, mapping(Account::getFirstName, toSet())));
}

/**
Expand All @@ -148,7 +177,9 @@ public Map<String, Set<String>> groupFirstNamesByLastNames() {
* @return a map where a key is a birthday month and value is comma-separated first names
*/
public Map<Month, String> groupCommaSeparatedFirstNamesByBirthdayMonth() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return accounts.stream()
.collect(groupingBy(a -> a.getBirthday().getMonth(),
mapping(Account::getFirstName, joining(", "))));
}

/**
Expand All @@ -158,7 +189,10 @@ public Map<Month, String> groupCommaSeparatedFirstNamesByBirthdayMonth() {
* @return a map where key is a creation month and value is total balance of all accounts created in that month
*/
public Map<Month, BigDecimal> groupTotalBalanceByCreationMonth() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return accounts.stream()
.collect(groupingBy(a -> a.getCreationDate().getMonth(),
mapping(Account::getBalance,
reducing(BigDecimal.ZERO, BigDecimal::add))));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't understand what means T identity, and how it works in the method "reduce".
Method ===> "reduce(T identity, BinaryOperator accumulator);"

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The value of identity will be used as a first value, when it reduces your stream. In case your stream is empty, reduce() will return identity value.

}

/**
Expand All @@ -168,7 +202,11 @@ public Map<Month, BigDecimal> groupTotalBalanceByCreationMonth() {
* @return a map where key is a letter and value is its count in all first names
*/
public Map<Character, Long> getCharacterFrequencyInFirstNames() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return accounts.stream()
.map(Account::getFirstName)
.flatMapToInt(String::chars)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please explain how works this function? The most important thing, what does method chars?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. Method String#chars() creates a IntStream of characters. (It's because char is basically an int, and JDK doesn't provide a special stream class to hold primitive characters). So, if you want to get a stream of primitive char, you get IntStream.

accounts.stream().map(Account::getFirstName) will return a Stream<String>, so if you will map each string element into a stream of its chars, you will get Stream<IntStream> - a stream of streams.

flatMapToInt(String::chars) is a complex operation that consists of two basic operations:

  • "MapToInt" which receives a mapper - function that maps String into an IntStream
  • "flat" transforms Stream<IntStream> into a IntStream, e.g. ((3, 4), (3, 5, 7), (4)) -> (3, 4, 3, 5, 7, 4). Makes it flat.

Now, when you have an IntStream that consists of character codes, you want to transform it into a Stream<Character>, because after you will want to group them into a Map<Character, Long>

  • mapToObj(c -> (char) c) uses a mapper that cast int to char, and then map char to object Character

Now, when you have a Stream<Character>, you can collect them into a map.

  • groupingBy(Function.identity(), counting()) will group characters using its real value (because Function.identity() maps each element into itself) as a key, and then will count occurrences of each element (counting()) and use that number as map value

.mapToObj(c -> (char) c)
.collect(groupingBy(identity(), counting()));
}

/**
Expand All @@ -178,7 +216,12 @@ public Map<Character, Long> getCharacterFrequencyInFirstNames() {
* @return a map where key is a letter and value is its count ignoring case in all first and last names
*/
public Map<Character, Long> getCharacterFrequencyIgnoreCaseInFirstAndLastNames() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return accounts.stream()
.flatMap(a -> Stream.of(a.getFirstName(), a.getLastName()))
.map(String::toLowerCase)
.flatMapToInt(String::chars)
.mapToObj(c -> (char) c)
.collect(groupingBy(identity(), counting()));
}

}
Expand Down
47 changes: 28 additions & 19 deletions crazy-lambdas/src/main/java/com/bobocode/CrazyLambdas.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package com.bobocode;

import java.math.BigDecimal;
import java.util.concurrent.ThreadLocalRandom;
import java.util.Map;
import java.util.TreeMap;
import java.util.function.*;

public class CrazyLambdas {
Expand All @@ -13,7 +13,7 @@ public class CrazyLambdas {
* @return a string supplier
*/
public static Supplier<String> helloSupplier() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return () -> "Hello";
}

/**
Expand All @@ -22,7 +22,7 @@ public static Supplier<String> helloSupplier() {
* @return a string predicate
*/
public static Predicate<String> isEmptyPredicate() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return String::isEmpty;
}

/**
Expand All @@ -32,7 +32,7 @@ public static Predicate<String> isEmptyPredicate() {
* @return function that repeats Strings
*/
public static BiFunction<String, Integer, String> stringMultiplier() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return String::repeat;
}

/**
Expand All @@ -42,7 +42,7 @@ public static BiFunction<String, Integer, String> stringMultiplier() {
* @return function that converts adds dollar sign
*/
public static Function<BigDecimal, String> toDollarStringFunction() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return bigDecimal -> "$" + bigDecimal;
}

/**
Expand All @@ -54,7 +54,7 @@ public static Function<BigDecimal, String> toDollarStringFunction() {
* @return a string predicate
*/
public static Predicate<String> lengthInRangePredicate(int min, int max) {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return str -> str.length() >= min && str.length() < max;
}

/**
Expand All @@ -63,7 +63,7 @@ public static Predicate<String> lengthInRangePredicate(int min, int max) {
* @return int supplier
*/
public static IntSupplier randomIntSupplier() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return () -> ThreadLocalRandom.current().nextInt();
}


Expand All @@ -73,7 +73,7 @@ public static IntSupplier randomIntSupplier() {
* @return int operation
*/
public static IntUnaryOperator boundedRandomIntSupplier() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return bound -> ThreadLocalRandom.current().nextInt(bound);
}

/**
Expand All @@ -82,7 +82,7 @@ public static IntUnaryOperator boundedRandomIntSupplier() {
* @return square operation
*/
public static IntUnaryOperator intSquareOperation() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return a -> a * a;
}

/**
Expand All @@ -91,7 +91,7 @@ public static IntUnaryOperator intSquareOperation() {
* @return binary sum operation
*/
public static LongBinaryOperator longSumOperation() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return (a, b) -> a + b;
}

/**
Expand All @@ -100,7 +100,7 @@ public static LongBinaryOperator longSumOperation() {
* @return string to int converter
*/
public static ToIntFunction<String> stringToIntConverter() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return Integer::parseInt;
}

/**
Expand All @@ -111,7 +111,7 @@ public static ToIntFunction<String> stringToIntConverter() {
* @return a function supplier
*/
public static Supplier<IntUnaryOperator> nMultiplyFunctionSupplier(int n) {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return () -> a -> n * a;
}

/**
Expand All @@ -120,7 +120,7 @@ public static Supplier<IntUnaryOperator> nMultiplyFunctionSupplier(int n) {
* @return function that composes functions with trim() function
*/
public static UnaryOperator<Function<String, String>> composeWithTrimFunction() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return stringFunction -> stringFunction.compose(String::trim);
}

/**
Expand All @@ -131,7 +131,11 @@ public static UnaryOperator<Function<String, String>> composeWithTrimFunction()
* @return a thread supplier
*/
public static Supplier<Thread> runningThreadSupplier(Runnable runnable) {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return () -> {
Thread thread = new Thread(runnable);
thread.start();
return thread;
};
}

/**
Expand All @@ -140,7 +144,7 @@ public static Supplier<Thread> runningThreadSupplier(Runnable runnable) {
* @return a runnable consumer
*/
public static Consumer<Runnable> newThreadRunnableConsumer() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return runnable -> new Thread(runnable).start();
}

/**
Expand All @@ -150,7 +154,11 @@ public static Consumer<Runnable> newThreadRunnableConsumer() {
* @return a function that transforms runnable into a thread supplier
*/
public static Function<Runnable, Supplier<Thread>> runnableToThreadSupplierFunction() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return runnable -> () -> {
Thread thread = new Thread(runnable);
thread.start();
return thread;
};
}

/**
Expand All @@ -163,7 +171,7 @@ public static Function<Runnable, Supplier<Thread>> runnableToThreadSupplierFunct
* @return a binary function that receiver predicate and function and compose them to create a new function
*/
public static BiFunction<IntUnaryOperator, IntPredicate, IntUnaryOperator> functionToConditionalFunction() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return (intOperation, intPredicate) -> a -> intPredicate.test(a) ? intOperation.applyAsInt(a) : a;
}

/**
Expand All @@ -174,7 +182,7 @@ public static BiFunction<IntUnaryOperator, IntPredicate, IntUnaryOperator> funct
* @return a high-order function that fetches a function from a function map by a given name or returns identity()
*/
public static BiFunction<Map<String, IntUnaryOperator>, String, IntUnaryOperator> functionLoader() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return (functionMap, functionName) -> functionMap.getOrDefault(functionName, IntUnaryOperator.identity());
}

/**
Expand All @@ -183,7 +191,8 @@ public static BiFunction<Map<String, IntUnaryOperator>, String, IntUnaryOperator
* @return a supplier instance
*/
public static Supplier<Supplier<Supplier<String>>> trickyWellDoneSupplier() {
throw new UnsupportedOperationException("It's your job to implement this method"); // todo
return () -> () -> () -> "WELL DONE!";
}
}


8 changes: 7 additions & 1 deletion math-functions/src/main/java/com.bobocode/Functions.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.bobocode;

import static java.lang.Math.abs;

public class Functions {
/**
* A static factory method that creates an integer function map with basic functions:
Expand All @@ -14,7 +16,11 @@ public class Functions {
public static FunctionMap<Integer, Integer> intFunctionMap() {
FunctionMap<Integer, Integer> intFunctionMap = new FunctionMap<>();

// todo: add simple functions to the function map (abs, sng, increment, decrement, square)
intFunctionMap.addFunction("square", n -> n * n);
intFunctionMap.addFunction("abs", Math::abs);
intFunctionMap.addFunction("increment", n -> n + 1);
intFunctionMap.addFunction("decrement", n -> n - 1);
intFunctionMap.addFunction("sgn", n -> (n != 0) ? n / abs(n) : 0);

return intFunctionMap;
}
Expand Down
Loading