Skip to content

Commit cc38c61

Browse files
authored
Merge pull request #2 from seniorglez/feature/Add-more-methods-to-Collection-Utils
Feature/add more methods to collection utils
2 parents e91e9c2 + d188e09 commit cc38c61

File tree

4 files changed

+312
-8
lines changed

4 files changed

+312
-8
lines changed

src/main/java/com/seniorglez/functionalJava/collections/CollectionsUtils.java

Lines changed: 131 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*Copyright (c) 2021 Diego Dominguez Gonzalez
1+
/*Copyright (c) 2022 Diego Dominguez Gonzalez
22
*
33
*Permission is hereby granted, free of charge, to any person obtaining a copy
44
*of this software and associated documentation files (the "Software"), to deal
@@ -25,11 +25,18 @@
2525

2626
import java.lang.reflect.Constructor;
2727
import java.util.Collection;
28+
import java.util.Collections;
29+
import java.util.Comparator;
2830
import java.util.Iterator;
31+
import java.util.LinkedList;
32+
import java.util.List;
2933
import java.util.function.BinaryOperator;
3034
import java.util.function.Function;
3135
import java.util.function.Predicate;
3236

37+
import static java.util.Objects.isNull;
38+
import static java.util.Objects.nonNull;
39+
3340
/**
3441
* This class consists exclusively of static methods that operate on or return collections.
3542
*
@@ -73,9 +80,9 @@ public static <T> Option<T> flat(Collection<T> collection, BinaryOperator<T> map
7380
Iterator<T> iterator = collection.iterator();
7481
if (!iterator.hasNext()) return new Option<T>();
7582
T result = iterator.next();
76-
while (iterator.hasNext() && result!=null) {
83+
while (iterator.hasNext() && nonNull(result)) {
7784
T aux = iterator.next();
78-
result =(aux==null)? null : mapper.apply(result, aux);
85+
result = (isNull(aux))? null : mapper.apply(result, aux);
7986
}
8087
return new Option<>(result);
8188
}
@@ -103,7 +110,126 @@ public static <T> Collection<T> filter(Collection<T> collection, Predicate<T> co
103110
* @param collection The collection to be filtered.
104111
*/
105112
public static <T> Collection<T> filterNotNull(Collection<T> collection) {
106-
return filter(collection,(A)-> A != null);
113+
return filter(collection,(A)-> nonNull(A) );
114+
}
115+
116+
/**
117+
* Returns a new List with the same items of the given Collection.
118+
*
119+
* @param collection The Collection used to generate the new List.
120+
*/
121+
public static <T> List<T> toList (Collection<T> collection) {
122+
Iterator<T> iterator = collection.iterator();
123+
List<T> list = new LinkedList<>();
124+
while( iterator.hasNext() ) {
125+
list.add(iterator.next());
126+
}
127+
return list;
128+
}
129+
130+
/**
131+
* Returns an Option wrapped the index of the given item inside the given collection. The Option's value will be present if the item is
132+
* actually in the collection, otherwise the optional will be empty.
133+
* @param collection The collection to search in.
134+
* @param item The item to look for.
135+
*/
136+
public static <T> Option<Integer> findIndex(Collection<T> collection, T item) {
137+
int index = toList(collection).indexOf(item);
138+
if( index >= 0 ) {
139+
return new Option<>(Integer.valueOf(index));
140+
}
141+
return new Option<>();
142+
}
143+
144+
/**
145+
* Returns true it there is at least one item in the given collection witch matches the given condition.
146+
* @param collection The given collection.
147+
* @param condition The given collection.
148+
*/
149+
public static <T> boolean anyMatch(Collection<T> collection, Predicate<T> condition) {
150+
if(isEmpty(collection)) {
151+
return false;
152+
}
153+
Collection<T> result = filter(collection, condition);
154+
return !isEmpty(result);
155+
}
156+
157+
/**
158+
* Returns true if the given collection is not null and is not empty.
159+
*
160+
* @param collection the given collection.
161+
*/
162+
public static <T> boolean isEmpty(Collection<T> collection) {
163+
if(isNull(collection) || collection.isEmpty()) {
164+
return true;
165+
}
166+
return false;
167+
}
168+
169+
/**
170+
* Return a new collection which the elements of the given collections.
171+
*
172+
* @param a First Collection given.
173+
* @param b Second Collection given.
174+
*/
175+
public static <T> Collection<T> concat(Collection<T> a, Collection<T> b) {
176+
a.addAll(b);
177+
return a;
178+
}
179+
180+
/**
181+
* Return a new List which the elements of the given Lists.
182+
*
183+
* @param a First List given.
184+
* @param b Second List given.
185+
*/
186+
public static <T> List<T> concat(List<T> a, List<T> b) {
187+
a.addAll(b);
188+
return a;
189+
}
190+
191+
/**
192+
* Return the first element of the given Collection.
193+
*
194+
* @param collection The given Collection.
195+
*/
196+
public static <T> T first(Collection<T> collection) {
197+
return toList(collection).get(0);
198+
}
199+
200+
/**
201+
* Return the last element of the given Collection.
202+
*
203+
* @param collection The given Collection.
204+
*/
205+
public static <T> T last(Collection<T> collection) {
206+
return toList(collection).get(collection.size() - 1);
207+
}
208+
209+
210+
/**
211+
* Return true if the collections have the same elements.
212+
*
213+
* @param a First Collection given.
214+
* @param b Second Collection given.
215+
* @param comparator The comparator needed to sort the elements.
216+
*/
217+
public static <T> boolean compareCollections(Collection<T> a, Collection<T> b, Comparator<T> comparator) {
218+
Collection <T> sortedA = sort(a, comparator);
219+
Collection <T> sortedB = sort(a, comparator);
220+
return sortedA.equals(sortedB);
221+
}
222+
223+
/**
224+
* Return a new sorted List from the given collection.
225+
*
226+
* @param collection The Collection given.
227+
* @param comparator The comparator needed to sort the elements.
228+
*/
229+
public static <T> List<T> sort(Collection<T> collection, Comparator<T> comparator) {
230+
List<T> list = toList(collection);
231+
Collections.sort(list,comparator);
232+
return list;
107233
}
108234

109235
//private methods
@@ -112,7 +238,7 @@ private static Collection instanceCollectionOf(Class<? extends Collection> tClas
112238
try {
113239
Constructor<? extends Collection> constructor = tClass.getConstructor();
114240
return constructor.newInstance();
115-
} catch (Exception e){
241+
} catch (Exception e) {
116242
throw new RuntimeException(e);
117243
}
118244
}

src/main/java/com/seniorglez/functionalJava/monads/Option.java

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@
2424
import java.util.function.Function;
2525
import java.util.function.Predicate;
2626

27+
import static java.util.Objects.isNull;
28+
import static java.util.Objects.nonNull;
29+
2730
/**
2831
* Wraps a value that can be null, thus avoiding {@link NullPointerException}. You can carry out all the transformations
2932
* you consider through the map function and then check if the value is null without fear of {@link NullPointerException}.
@@ -59,7 +62,7 @@ public Option(){
5962
* @return An Option that wraps the value resulting from the execution of the action on the current value.
6063
*/
6164
public <U> Option<U> flatMap(Function<? super T, ? extends U> mapper) {
62-
return (this.value == null) ? new Option<U>() : new Option<U>(mapper.apply(value));
65+
return (isNull(this.value)) ? new Option<U>() : new Option<U>(mapper.apply(value));
6366
}
6467

6568
/**
@@ -85,14 +88,22 @@ public boolean check(Predicate<? super T> condition) {
8588
* @param other The alternative value.
8689
*/
8790
public T orElse(T other) {
88-
return value !=null? value : other;
91+
return nonNull(value) ? value : other;
8992
}
9093

9194
/**
9295
* Returns the value wrapped by the Option.
93-
* @return The value
96+
* @return The value.
9497
*/
9598
public T getValue() {
9699
return this.value;
97100
}
101+
102+
/**
103+
* Returns true if the value wrapped by the Optional is not null.
104+
* @return True if the value wrapped by the Optional is not null.
105+
*/
106+
public boolean isPresent() {
107+
return nonNull(this.value);
108+
}
98109
}

src/test/java/com/seniorglez/functionalJava/collections/TestCollectionsUtils.java

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,18 @@
44
import org.junit.Test;
55

66
import java.util.Collection;
7+
import java.util.Comparator;
78
import java.util.LinkedList;
9+
import java.util.List;
810

11+
import static com.seniorglez.functionalJava.collections.CollectionsUtils.anyMatch;
12+
import static com.seniorglez.functionalJava.collections.CollectionsUtils.compareCollections;
13+
import static com.seniorglez.functionalJava.collections.CollectionsUtils.concat;
14+
import static com.seniorglez.functionalJava.collections.CollectionsUtils.findIndex;
15+
import static com.seniorglez.functionalJava.collections.CollectionsUtils.first;
16+
import static com.seniorglez.functionalJava.collections.CollectionsUtils.isEmpty;
17+
import static com.seniorglez.functionalJava.collections.CollectionsUtils.last;
18+
import static com.seniorglez.functionalJava.collections.CollectionsUtils.sort;
919
import static org.junit.Assert.assertTrue;
1020

1121
public class TestCollectionsUtils {
@@ -157,4 +167,147 @@ public void testFilterNotNull() {
157167
assertTrue(result.size() == 10);
158168
result.forEach(A -> assertTrue(A != null));
159169
}
170+
171+
@Test
172+
public void testFindIndexShouldReturnOptionNOTPresent() {
173+
LinkedList<String> ll = new LinkedList<>();
174+
ll.add("Pepe");
175+
ll.add("Juan");
176+
ll.add("Carlos");
177+
ll.add("Jon Ander");
178+
Option<Integer> option = findIndex(ll,"Alma");
179+
assertTrue( !option.isPresent() );
180+
}
181+
182+
@Test
183+
public void testFindIndexShouldReturnOptionISPresent() {
184+
LinkedList<String> ll = new LinkedList<>();
185+
ll.add("Pepe");
186+
ll.add("Juan");
187+
ll.add("Carlos");
188+
ll.add("Jon Ander");
189+
Option<Integer> option = findIndex(ll,"Carlos");
190+
assertTrue( option.isPresent() );
191+
}
192+
193+
@Test
194+
public void testIsEmptyShouldReturnTrueWhenTheCollectionIsNull() {
195+
LinkedList<String> ll = null;
196+
assertTrue(isEmpty(ll));
197+
}
198+
199+
@Test
200+
public void testIsEmptyShouldReturnTrueWhenTheCollectionHasNoItems() {
201+
LinkedList<String> ll = new LinkedList<>();
202+
assertTrue(isEmpty(ll));
203+
}
204+
205+
@Test
206+
public void testIsEmptyShouldReturnFalseIfTheCollectionHasItems() {
207+
LinkedList<String> ll = new LinkedList<>();
208+
ll.add("Atocha");
209+
assertTrue(!isEmpty(ll));
210+
}
211+
212+
@Test
213+
public void testAnyMatchShouldReturnFalseIfThereIsNoMatch() {
214+
LinkedList<String> ll = new LinkedList<>();
215+
ll.add("Atocha");
216+
assertTrue(!anyMatch(ll, a -> a.length() > 100000000));
217+
}
218+
219+
@Test
220+
public void testAnyMatchShouldReturnTrueIfThereIsAlLeastOneMatch() {
221+
LinkedList<String> ll = new LinkedList<>();
222+
ll.add("Atocha");
223+
assertTrue(anyMatch(ll, a -> a.length() > 0));
224+
}
225+
226+
@Test
227+
public void testAnyMarchShouldReturnFalseIfTheCollectionIsNull() {
228+
LinkedList<String> ll = null;
229+
assertTrue(!anyMatch(ll, a -> a.length() > 0));
230+
}
231+
232+
@Test
233+
public void testConcatShouldReturnTheFirstItemOfTheFirstList() {
234+
LinkedList<String> lla = new LinkedList<>();
235+
lla.add("Gorri");
236+
lla.add("Beltz");
237+
LinkedList<String> llb = new LinkedList<>();
238+
llb.add("Hori");
239+
llb.add("Urdin");
240+
List<String> llc = concat(lla,llb);
241+
assertTrue(llc.get(0) == "Gorri");
242+
}
243+
244+
@Test
245+
public void testConcatShouldReturnTheLastItemOfTheSecondList() {
246+
LinkedList<String> lla = new LinkedList<>();
247+
lla.add("Gorri");
248+
lla.add("Beltz");
249+
LinkedList<String> llb = new LinkedList<>();
250+
llb.add("Hori");
251+
llb.add("Urdin");
252+
List<String> llc = concat(lla,llb);
253+
assertTrue(llc.get(3) == "Urdin");
254+
}
255+
256+
@Test
257+
public void testConcatShouldHaveTheSumOfBothCollectionSizes() {
258+
Collection<String> a = new LinkedList<>();
259+
a.add("Gorri");
260+
a.add("Beltz");
261+
Collection<String> b = new LinkedList<>();
262+
b.add("Hori");
263+
b.add("Urdin");
264+
Collection<String> c = concat(a,b);
265+
assertTrue(c.size() == 4);
266+
}
267+
268+
@Test
269+
public void testFirst() {
270+
Collection<String> a = new LinkedList<>();
271+
a.add("Gorri");
272+
a.add("Beltz");
273+
a.add("Hori");
274+
a.add("Urdin");
275+
assertTrue(first(a) == "Gorri");
276+
}
277+
278+
@Test
279+
public void testLast() {
280+
Collection<String> a = new LinkedList<>();
281+
a.add("Gorri");
282+
a.add("Beltz");
283+
a.add("Hori");
284+
a.add("Urdin");
285+
assertTrue(last(a) == "Urdin");
286+
}
287+
288+
@Test
289+
public void testCompareCollectionsShouldReturnTrue() {
290+
Collection<String> a = new LinkedList<>();
291+
a.add("Gorri");
292+
a.add("Beltz");
293+
a.add("Hori");
294+
a.add("Urdin");
295+
Collection<String> b = new LinkedList<>();
296+
b.add("Beltz");
297+
b.add("Gorri");
298+
b.add("Hori");
299+
b.add("Urdin");
300+
assertTrue(compareCollections(a,b, Comparator.naturalOrder()));
301+
}
302+
303+
@Test
304+
public void testNaturalOrderSort() {
305+
Collection<String> a = new LinkedList<>();
306+
a.add("Gorri");
307+
a.add("Beltz");
308+
a.add("Hori");
309+
a.add("Urdin");
310+
assertTrue(sort(a, Comparator.naturalOrder()).get(0).equals("Beltz"));
311+
}
312+
160313
}

0 commit comments

Comments
 (0)