11package com .bobocode .fp ;
22
3+ import com .bobocode .fp .exception .EntityNotFoundException ;
34import com .bobocode .model .Account ;
5+ import com .bobocode .model .Sex ;
46import com .bobocode .util .ExerciseNotCompletedException ;
57import lombok .AllArgsConstructor ;
68
79import java .math .BigDecimal ;
810import java .time .Month ;
911import java .util .*;
12+ import java .util .function .Function ;
13+ import java .util .stream .Collectors ;
14+
15+ import static java .util .stream .Collectors .counting ;
16+ import static java .util .stream .Collectors .groupingBy ;
17+ import static java .util .stream .Collectors .joining ;
18+ import static java .util .stream .Collectors .mapping ;
19+ import static java .util .stream .Collectors .reducing ;
20+ import static java .util .stream .Collectors .toSet ;
1021
1122/**
1223 * {@link CrazyStreams} is an exercise class. Each method represent some operation with a collection of accounts that
@@ -29,8 +40,11 @@ public class CrazyStreams {
2940 *
3041 * @return account with max balance wrapped with optional
3142 */
43+
3244 public Optional <Account > findRichestPerson () {
33- throw new ExerciseNotCompletedException ();
45+ return accounts .stream ()
46+ .sorted (Comparator .comparing (Account ::getBalance ).reversed ())
47+ .findFirst ();
3448 }
3549
3650 /**
@@ -40,7 +54,9 @@ public Optional<Account> findRichestPerson() {
4054 * @return a list of accounts
4155 */
4256 public List <Account > findAccountsByBirthdayMonth (Month birthdayMonth ) {
43- throw new ExerciseNotCompletedException ();
57+ return accounts .stream ()
58+ .filter (a -> a .getBirthday ().getMonth () == birthdayMonth )
59+ .collect (Collectors .toList ());
4460 }
4561
4662 /**
@@ -49,8 +65,12 @@ public List<Account> findAccountsByBirthdayMonth(Month birthdayMonth) {
4965 *
5066 * @return a map where key is true or false, and value is list of male, and female accounts
5167 */
68+
5269 public Map <Boolean , List <Account >> partitionMaleAccounts () {
53- throw new ExerciseNotCompletedException ();
70+ return accounts .stream ()
71+ .collect (Collectors .groupingBy (a -> a .getSex ().equals (Sex .MALE ),
72+ Collectors .toList ()));
73+
5474 }
5575
5676 /**
@@ -59,8 +79,12 @@ public Map<Boolean, List<Account>> partitionMaleAccounts() {
5979 *
6080 * @return a map where key is an email domain and value is a list of all account with such email
6181 */
82+
83+
6284 public Map <String , List <Account >> groupAccountsByEmailDomain () {
63- throw new ExerciseNotCompletedException ();
85+ return accounts .stream ()
86+ .collect (Collectors .groupingBy (a -> a .getEmail ().split ("@" )[1 ],
87+ Collectors .toList ()));
6488 }
6589
6690 /**
@@ -69,7 +93,11 @@ public Map<String, List<Account>> groupAccountsByEmailDomain() {
6993 * @return total number of letters of first and last names of all accounts
7094 */
7195 public int getNumOfLettersInFirstAndLastNames () {
72- throw new ExerciseNotCompletedException ();
96+ return accounts .stream ()
97+ .map (a -> a .getFirstName ().toCharArray ().length
98+ + a .getLastName ().toCharArray ().length )
99+ .mapToInt (Integer ::valueOf )
100+ .sum ();
73101 }
74102
75103 /**
@@ -78,16 +106,23 @@ public int getNumOfLettersInFirstAndLastNames() {
78106 * @return total balance of all accounts
79107 */
80108 public BigDecimal calculateTotalBalance () {
81- throw new ExerciseNotCompletedException ();
109+ return BigDecimal .valueOf (accounts .stream ()
110+ .map (Account ::getBalance )
111+ .mapToInt (BigDecimal ::intValue )
112+ .sum ());
82113 }
83114
84115 /**
85116 * Returns a {@link List} of {@link Account} objects sorted by first and last names.
86117 *
87118 * @return list of accounts sorted by first and last names
88119 */
120+
89121 public List <Account > sortByFirstAndLastNames () {
90- throw new ExerciseNotCompletedException ();
122+ return accounts .stream ()
123+ .sorted (Comparator .comparing (Account ::getFirstName )
124+ .thenComparing (Account ::getLastName ))
125+ .collect (Collectors .toList ());
91126 }
92127
93128 /**
@@ -97,7 +132,9 @@ public List<Account> sortByFirstAndLastNames() {
97132 * @return true if there is an account that has an email with provided domain
98133 */
99134 public boolean containsAccountWithEmailDomain (String emailDomain ) {
100- throw new ExerciseNotCompletedException ();
135+ return accounts .stream ()
136+ .map (a -> a .getEmail ().split ("@" )[1 ])
137+ .anyMatch (e -> e .equals (emailDomain ));
101138 }
102139
103140 /**
@@ -108,7 +145,11 @@ public boolean containsAccountWithEmailDomain(String emailDomain) {
108145 * @return account balance
109146 */
110147 public BigDecimal getBalanceByEmail (String email ) {
111- throw new ExerciseNotCompletedException ();
148+ return accounts .stream ()
149+ .filter (a -> a .getEmail ().equals (email ))
150+ .map (Account ::getBalance )
151+ .findFirst ()
152+ .orElseThrow (() -> new EntityNotFoundException ("Cannot find Account by email=" + email ));
112153 }
113154
114155 /**
@@ -117,7 +158,11 @@ public BigDecimal getBalanceByEmail(String email) {
117158 * @return map of accounts by its ids
118159 */
119160 public Map <Long , Account > collectAccountsById () {
120- throw new ExerciseNotCompletedException ();
161+ return accounts .stream ()
162+ .collect (Collectors .toMap (
163+ Account ::getId ,
164+ a -> a
165+ ));
121166 }
122167
123168 /**
@@ -128,7 +173,12 @@ public Map<Long, Account> collectAccountsById() {
128173 * @return map of account by its ids the were created in a particular year
129174 */
130175 public Map <String , BigDecimal > collectBalancesByEmailForAccountsCreatedOn (int year ) {
131- throw new ExerciseNotCompletedException ();
176+ return accounts .stream ()
177+ .filter (a -> a .getCreationDate ().getYear () == year )
178+ .collect (Collectors .toMap (
179+ Account ::getEmail ,
180+ Account ::getBalance
181+ ));
132182 }
133183
134184 /**
@@ -138,7 +188,11 @@ public Map<String, BigDecimal> collectBalancesByEmailForAccountsCreatedOn(int ye
138188 * @return a map where key is a last name and value is a set of first names
139189 */
140190 public Map <String , Set <String >> groupFirstNamesByLastNames () {
141- throw new ExerciseNotCompletedException ();
191+ return accounts .stream ()
192+ .collect (Collectors .groupingBy (
193+ Account ::getLastName ,
194+ mapping (Account ::getFirstName , toSet ())
195+ ));
142196 }
143197
144198 /**
@@ -148,7 +202,12 @@ public Map<String, Set<String>> groupFirstNamesByLastNames() {
148202 * @return a map where a key is a birthday month and value is comma-separated first names
149203 */
150204 public Map <Month , String > groupCommaSeparatedFirstNamesByBirthdayMonth () {
151- throw new ExerciseNotCompletedException ();
205+ return accounts .stream ()
206+ .collect (Collectors .groupingBy (
207+ a -> a .getBirthday ().getMonth (),
208+ mapping (Account ::getFirstName , joining (", " ))
209+
210+ ));
152211 }
153212
154213 /**
@@ -158,7 +217,11 @@ public Map<Month, String> groupCommaSeparatedFirstNamesByBirthdayMonth() {
158217 * @return a map where key is a creation month and value is total balance of all accounts created in that month
159218 */
160219 public Map <Month , BigDecimal > groupTotalBalanceByCreationMonth () {
161- throw new ExerciseNotCompletedException ();
220+ return accounts .stream ()
221+ .collect (Collectors .groupingBy (
222+ a -> a .getCreationDate ().getMonth (),
223+ reducing (BigDecimal .ZERO ,Account ::getBalance , BigDecimal ::add )
224+ ));
162225 }
163226
164227 /**
@@ -168,7 +231,14 @@ public Map<Month, BigDecimal> groupTotalBalanceByCreationMonth() {
168231 * @return a map where key is a letter and value is its count in all first names
169232 */
170233 public Map <Character , Long > getCharacterFrequencyInFirstNames () {
171- throw new ExerciseNotCompletedException ();
234+ return accounts .stream ()
235+ .map (Account ::getFirstName )
236+ .flatMapToInt (String ::chars )
237+ .mapToObj (c -> (char ) c )
238+ .collect (Collectors .groupingBy (
239+ c -> c ,
240+ counting ()
241+ ));
172242 }
173243
174244 /**
@@ -179,8 +249,24 @@ public Map<Character, Long> getCharacterFrequencyInFirstNames() {
179249 * @return a map where key is a letter and value is its count ignoring case in all first and last names
180250 */
181251 public Map <Character , Long > getCharacterFrequencyIgnoreCaseInFirstAndLastNames (int nameLengthBound ) {
182- throw new ExerciseNotCompletedException ();
183- }
252+ Function <Account , String > function = account -> {
253+ String result = "" ;
254+ if (account .getFirstName ().length () >= nameLengthBound ) {
255+ result += account .getFirstName ();
256+ }
257+ if (account .getLastName ().length () >= nameLengthBound ) {
258+ result += account .getLastName ();
259+ }
260+ return result .toLowerCase ();
261+ };
184262
263+ return accounts .stream ()
264+ .map (function )
265+ .flatMapToInt (String ::chars )
266+ .mapToObj (c -> (char ) c )
267+ .collect (groupingBy (
268+ c -> c ,
269+ counting ()
270+ ));
271+ }
185272}
186-
0 commit comments