Skip to content

Commit a7cb0be

Browse files
committed
add ability to collect to map
1 parent 67f38fc commit a7cb0be

2 files changed

Lines changed: 141 additions & 0 deletions

File tree

src/main/java/it/aboutbits/springboot/toolbox/util/CollectUtil.java

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import java.util.Collection;
77
import java.util.List;
8+
import java.util.Map;
89
import java.util.Objects;
910
import java.util.Set;
1011
import java.util.function.Function;
@@ -80,4 +81,34 @@ public static <T, R> Stream<R> collectToStream(@NonNull Stream<T> items, @NonNul
8081
.map(mapper)
8182
.filter(Objects::nonNull);
8283
}
84+
85+
public static <T, K, R> Map<K, R> collectToMap(
86+
@NonNull Collection<T> items,
87+
@NonNull Function<T, K> keyMapper,
88+
@NonNull Function<T, R> valueMapper
89+
) {
90+
return items.stream()
91+
.filter(Objects::nonNull)
92+
.collect(Collectors.toMap(keyMapper, valueMapper));
93+
}
94+
95+
public static <T, K, R> Map<K, R> collectToMap(
96+
@NonNull Streamable<T> items,
97+
@NonNull Function<T, K> keyMapper,
98+
@NonNull Function<T, R> valueMapper
99+
) {
100+
return items.stream()
101+
.filter(Objects::nonNull)
102+
.collect(Collectors.toMap(keyMapper, valueMapper));
103+
}
104+
105+
public static <T, K, R> Map<K, R> collectToMap(
106+
@NonNull Stream<T> items,
107+
@NonNull Function<T, K> keyMapper,
108+
@NonNull Function<T, R> valueMapper
109+
) {
110+
return items
111+
.filter(Objects::nonNull)
112+
.collect(Collectors.toMap(keyMapper, valueMapper));
113+
}
83114
}

src/test/java/it/aboutbits/springboot/toolbox/util/CollectUtilTest.java

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
import java.util.Arrays;
99
import java.util.Collections;
1010
import java.util.function.Function;
11+
import java.util.stream.Stream;
1112

1213
import static org.assertj.core.api.Assertions.assertThat;
14+
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
1315
import static org.junit.jupiter.api.Assertions.assertEquals;
1416
import static org.junit.jupiter.api.Assertions.assertTrue;
1517

@@ -368,4 +370,112 @@ void shouldHandleEmptyStreamWhenConvertingToStream() {
368370
assertTrue(result.isEmpty());
369371
}
370372
}
373+
374+
@Nested
375+
class CollectToMap {
376+
@Test
377+
@DisplayName("Should convert Collection to Map using key and value mappers")
378+
void shouldConvertCollectionToMapUsingMappers() {
379+
// given
380+
var items = Arrays.asList("a", "bb", "ccc");
381+
382+
// when
383+
var result = CollectUtil.collectToMap(items, String::length, Function.identity());
384+
385+
// then
386+
assertThat(result)
387+
.containsEntry(1, "a")
388+
.containsEntry(2, "bb")
389+
.containsEntry(3, "ccc")
390+
.hasSize(3);
391+
}
392+
393+
@Test
394+
@DisplayName("Should throw on duplicate keys according to Collectors.toMap default behavior")
395+
void shouldThrowOnDuplicateKeys() {
396+
// given
397+
var items = Arrays.asList("a", "b"); // both have length of 1
398+
399+
// when / then
400+
assertThatIllegalStateException().isThrownBy(
401+
() ->
402+
CollectUtil.collectToMap(
403+
items,
404+
String::length,
405+
Function.identity()
406+
)
407+
);
408+
}
409+
410+
@Test
411+
@DisplayName("Should convert Streamable to Map using key and value mappers")
412+
void shouldConvertStreamableToMapUsingMappers() {
413+
// given
414+
var items = Streamable.of("x", "yy");
415+
416+
// when
417+
var result = CollectUtil.collectToMap(items, String::length, Function.identity());
418+
419+
// then
420+
assertThat(result)
421+
.containsEntry(1, "x")
422+
.containsEntry(2, "yy")
423+
.hasSize(2);
424+
}
425+
426+
@Test
427+
@DisplayName("Should convert Stream to Map using key and value mappers")
428+
void shouldConvertStreamToMapUsingMappers() {
429+
// given
430+
var items = Stream.of("m", "nn");
431+
432+
// when
433+
var result = CollectUtil.collectToMap(items, String::length, Function.identity());
434+
435+
// then
436+
assertThat(result)
437+
.containsEntry(1, "m")
438+
.containsEntry(2, "nn")
439+
.hasSize(2);
440+
}
441+
442+
@Test
443+
@DisplayName("Should return empty map for empty collection")
444+
void shouldReturnEmptyMapForEmptyCollection() {
445+
// given
446+
var items = Collections.<String>emptyList();
447+
448+
// when
449+
var result = CollectUtil.collectToMap(items, String::length, Function.identity());
450+
451+
// then
452+
assertThat(result).isEmpty();
453+
}
454+
455+
@Test
456+
@DisplayName("Should return empty map for empty streamable")
457+
void shouldReturnEmptyMapForEmptyStreamable() {
458+
// given
459+
var items = Streamable.<String>empty();
460+
461+
// when
462+
var result = CollectUtil.collectToMap(items, String::length, Function.identity());
463+
464+
// then
465+
assertThat(result).isEmpty();
466+
}
467+
468+
@Test
469+
@DisplayName("Should return empty map for empty stream")
470+
void shouldReturnEmptyMapForEmptyStream() {
471+
// given
472+
var items = Stream.<String>empty();
473+
474+
// when
475+
var result = CollectUtil.collectToMap(items, String::length, Function.identity());
476+
477+
// then
478+
assertThat(result).isEmpty();
479+
}
480+
}
371481
}

0 commit comments

Comments
 (0)