Skip to content
This repository has been 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

Exercise/completed #2

wants to merge 27 commits into from

Conversation

tboychuk
Copy link
Collaborator

Complete exercises:

  • MathFunctions
  • CrazyLambdas
  • AccountAnalytics
  • SumOfSquares

@tboychuk tboychuk self-assigned this Aug 14, 2018
@bobocode-projects bobocode-projects deleted a comment from Podolian Aug 14, 2018
@@ -46,7 +55,8 @@ private AccountAnalytics(Collection<Account> accounts) {
* @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

@@ -56,7 +66,8 @@ private AccountAnalytics(Collection<Account> accounts) {
* @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. "[email protected]".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.

Copy link
Collaborator Author

@tboychuk tboychuk left a comment

Choose a reason for hiding this comment

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

Answered question

@@ -46,7 +55,8 @@ private AccountAnalytics(Collection<Account> accounts) {
* @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
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()

@@ -46,7 +55,8 @@ private AccountAnalytics(Collection<Account> accounts) {
* @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
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

@@ -56,7 +66,8 @@ private AccountAnalytics(Collection<Account> accounts) {
* @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]));
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. "[email protected]".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.

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

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

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.

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? Не дает сделать Идея лямбду.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants