This repository was archived by the owner on Feb 10, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 23
Expand file tree
/
Copy pathAccountAnalytics.java
More file actions
174 lines (153 loc) · 6.39 KB
/
AccountAnalytics.java
File metadata and controls
174 lines (153 loc) · 6.39 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
package com.bobocode;
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.stream.Collectors.*;
/**
* Implement methods using Stream API
*/
public class AccountAnalytics {
private Collection<Account> accounts;
public static AccountAnalytics of(Collection<Account> accounts) {
return new AccountAnalytics(accounts);
}
private AccountAnalytics(Collection<Account> accounts) {
this.accounts = accounts;
}
/**
* Returns {@link Optional} that contains an {@link Account} with the max value of balance
*
* @return account with max balance wrapped with optional
*/
public Optional<Account> findRichestPerson() {
return accounts.stream()
.max(comparing(Account::getBalance));
}
/**
* Returns a {@link List} of {@link Account} that have a birthday month equal to provided.
*
* @param birthdayMonth a month of birth
* @return a list of accounts
*/
public List<Account> findAccountsByBirthdayMonth(Month birthdayMonth) {
return accounts.stream()
.filter(a -> a.getBirthday().getMonth().equals(birthdayMonth))
.collect(toList());
}
/**
* Returns a map that separates all accounts into two lists - male and female. Map has two keys {@code true} indicates
* male list, and {@code false} indicates female list.
*
* @return a map where key is true or false, and value is list of male, and female accounts
*/
public Map<Boolean, List<Account>> partitionMaleAccounts() {
return accounts.stream()
.collect(partitioningBy(a -> a.getSex().equals(Sex.MALE)));
}
/**
* Returns a {@link Map} that stores accounts grouped by its email domain. A map key is {@link String} which is an
* email domain like "gmail.com". And the value is a {@link List} of {@link Account} objects with a specific email domain.
*
* @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() {
return accounts.stream()
.collect(groupingBy(a -> a.getEmail().split("@")[1]));
}
/**
* Returns a number of letters in all first and last names.
*
* @return total number of letters of first and last names of all accounts
*/
public int getNumOfLettersInFirstAndLastNames() {
return accounts.stream()
.mapToInt(a -> a.getFirstName().length() + a.getLastName().length())
.sum();
}
/**
* Returns a total balance of all accounts.
*
* @return total balance of all accounts
*/
public BigDecimal calculateTotalBalance() {
return accounts.stream()
.map(Account::getBalance)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
/**
* Returns a {@link List} of {@link Account} objects sorted by first and last names.
*
* @return list of accounts sorted by first and last names
*/
public List<Account> sortByFirstAndLastNames() {
return accounts.stream()
.sorted(comparing(Account::getFirstName)
.thenComparing(Account::getLastName))
.collect(toList());
}
/**
* Returns a {@link Map} where key is {@link Account#lastName} and values is a {@link Set} that contains first names
* of all accounts with a specific last name.
*
* @return a map where key is a first name and value is a set of first names
*/
public Map<String, Set<String>> groupFirstNamesByLastNames() {
return accounts.stream()
.collect(groupingBy(Account::getLastName, mapping(Account::getFirstName, toSet())));
}
/**
* Returns a {@link Map} where key is a birthday month, and value is a {@link String} that stores comma-separated
* first names, of all accounts that have the same birthday month.
*
* @return a map where a key is a birthday month and value is comma-separated first names
*/
public Map<Month, String> groupCommaSeparatedFirstNamesByBirthdayMonth() {
return accounts.stream()
.collect(groupingBy(a -> a.getBirthday().getMonth(),
mapping(Account::getFirstName, joining(", "))));
}
/**
* Returns a {@link Map} where key is a {@link Month} of {@link Account#creationDate}, and value is total balance
* of all accounts that have the same value creation month.
*
* @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() {
return accounts.stream()
.collect(groupingBy(a -> a.getCreationDate().getMonth(),
mapping(Account::getBalance,
reducing(BigDecimal.ZERO, BigDecimal::add))));
}
/**
* Returns a {@link Map} where key is a letter {@link Character}, and value is a number of its occurrences in
* {@link Account#firstName}.
*
* @return a map where key is a letter and value is its count in all first names
*/
public Map<Character, Long> getCharacterFrequencyInFirstNames() {
return accounts.stream()
.map(Account::getFirstName)
.flatMapToInt(String::chars)
.mapToObj(c -> (char) c)
.collect(groupingBy(Function.identity(), counting()));
}
/**
* Returns a {@link Map} where key is a letter {@link Character}, and value is a number of its occurrences ignoring
* case, in all {@link Account#firstName} and {@link Account#lastName}.
*
* @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() {
return accounts.stream()
.flatMap(a -> Stream.of(a.getFirstName(), a.getLastName()))
.map(String::toLowerCase)
.flatMapToInt(String::chars)
.mapToObj(c -> (char) c)
.collect(groupingBy(Function.identity(), counting()));
}
}