Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions src/main/java/it/aboutbits/springboot/toolbox/util/FilterUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package it.aboutbits.springboot.toolbox.util;

import lombok.NonNull;
import org.springframework.data.util.Streamable;

import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* This is a collection of tools to simply filter items to a new collection or stream.
* <p>
* The returned collections are unmodifiable.
*/
public final class FilterUtil {
private FilterUtil() {
}

public static <T> Set<T> filterToSet(@NonNull Collection<T> items, @NonNull Predicate<T> filter) {
return items.stream()
.filter(filter)
.collect(Collectors.toUnmodifiableSet());
}

public static <T> Set<T> filterToSet(@NonNull Streamable<T> items, @NonNull Predicate<T> filter) {
return items.stream()
.filter(filter)
.collect(Collectors.toUnmodifiableSet());
}

public static <T> Set<T> filterToSet(@NonNull Stream<T> items, @NonNull Predicate<T> filter) {
return items
.filter(filter)
.collect(Collectors.toUnmodifiableSet());
}

public static <T> List<T> filterToList(@NonNull Collection<T> items, @NonNull Predicate<T> filter) {
return items.stream()
.filter(filter)
.toList();
}

public static <T> List<T> filterToList(@NonNull Streamable<T> items, @NonNull Predicate<T> filter) {
return items.stream()
.filter(filter)
.toList();
}

public static <T> List<T> filterToList(@NonNull Stream<T> items, @NonNull Predicate<T> filter) {
return items
.filter(filter)
.toList();
}

public static <T> Stream<T> filterToStream(@NonNull Collection<T> items, @NonNull Predicate<T> filter) {
return items.stream()
.filter(filter);
}

public static <T> Stream<T> filterToStream(@NonNull Streamable<T> items, @NonNull Predicate<T> filter) {
return items.stream()
.filter(filter);
}

public static <T> Stream<T> filterToStream(@NonNull Stream<T> items, @NonNull Predicate<T> filter) {
return items
.filter(filter);
}
}
265 changes: 265 additions & 0 deletions src/test/java/it/aboutbits/springboot/toolbox/util/FilterUtilTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
package it.aboutbits.springboot.toolbox.util;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.data.util.Streamable;

import java.util.Arrays;
import java.util.Collections;
import java.util.stream.Stream;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertTrue;

class FilterUtilTest {
@Nested
class FilterToSet {
@Test
@DisplayName("Should filter Collection to Set using predicate")
void shouldFilterCollectionToSetUsingPredicate() {
// given
var numbers = Arrays.asList(1, 2, 3, 4, 5);

// when
var result = FilterUtil.filterToSet(numbers, n -> n > 2);

// then
assertThat(result).containsExactlyInAnyOrder(3, 4, 5);
}

@Test
@DisplayName("Should handle empty Collection when filtering to Set")
void shouldHandleEmptyCollectionWhenFilteringToSet() {
// given
var emptyList = Collections.<Integer>emptyList();

// when
var result = FilterUtil.filterToSet(emptyList, n -> n > 2);

// then
assertTrue(result.isEmpty());
}

@Test
@DisplayName("Should remove duplicates when filtering Collection to Set")
void shouldRemoveDuplicatesWhenFilteringCollectionToSet() {
// given
var numbersWithDuplicates = Arrays.asList(1, 2, 2, 3, 3, 3);

// when
var result = FilterUtil.filterToSet(numbersWithDuplicates, n -> n >= 2);

// then
assertThat(result).containsExactlyInAnyOrder(2, 3);
assertThat(result).hasSize(2);
}

@Test
@DisplayName("Should filter Streamable to Set using predicate")
void shouldFilterStreamableToSetUsingPredicate() {
// given
var numbers = Streamable.of(1, 2, 3, 4, 5);

// when
var result = FilterUtil.filterToSet(numbers, n -> n % 2 == 0);

// then
assertThat(result).containsExactlyInAnyOrder(2, 4);
}

@Test
@DisplayName("Should handle empty Streamable when filtering to Set")
void shouldHandleEmptyStreamableWhenFilteringToSet() {
// given
var emptyStreamable = Streamable.<Integer>empty();

// when
var result = FilterUtil.filterToSet(emptyStreamable, n -> n > 2);

// then
assertTrue(result.isEmpty());
}

@Test
@DisplayName("Should remove duplicates when filtering Stream to Set")
void shouldRemoveDuplicatesWhenFilteringStreamToSet() {
// given
var numbersWithDuplicates = Stream.of(1, 2, 2, 3, 3, 3);

// when
var result = FilterUtil.filterToSet(numbersWithDuplicates, n -> n >= 2);

// then
assertThat(result).containsExactlyInAnyOrder(2, 3);
assertThat(result).hasSize(2);
}
}

@Nested
class FilterToList {
@Test
@DisplayName("Should filter Collection to List using predicate")
void shouldFilterCollectionToListUsingPredicate() {
// given
var numbers = Arrays.asList(1, 2, 3, 4, 5);

// when
var result = FilterUtil.filterToList(numbers, n -> n % 2 == 1);

// then
assertThat(result).containsExactly(1, 3, 5);
}

@Test
@DisplayName("Should handle empty Collection when filtering to List")
void shouldHandleEmptyCollectionWhenFilteringToList() {
// given
var emptyList = Collections.<Integer>emptyList();

// when
var result = FilterUtil.filterToList(emptyList, n -> n > 2);

// then
assertTrue(result.isEmpty());
}

@Test
@DisplayName("Should preserve duplicates when filtering Collection to List")
void shouldPreserveDuplicatesWhenFilteringCollectionToList() {
// given
var numbersWithDuplicates = Arrays.asList(1, 2, 2, 3, 3, 3);

// when
var result = FilterUtil.filterToList(numbersWithDuplicates, n -> n >= 2);

// then
assertThat(result).containsExactly(2, 2, 3, 3, 3);
assertThat(result).hasSize(5);
}

@Test
@DisplayName("Should filter Streamable to List using predicate")
void shouldFilterStreamableToListUsingPredicate() {
// given
var numbers = Streamable.of(1, 2, 3, 4, 5);

// when
var result = FilterUtil.filterToList(numbers, n -> n < 4);

// then
assertThat(result).containsExactly(1, 2, 3);
}

@Test
@DisplayName("Should handle empty Streamable when filtering to List")
void shouldHandleEmptyStreamableWhenFilteringToList() {
// given
var emptyStreamable = Streamable.<Integer>empty();

// when
var result = FilterUtil.filterToList(emptyStreamable, n -> n > 2);

// then
assertTrue(result.isEmpty());
}

@Test
@DisplayName("Should preserve duplicates when filtering Stream to List")
void shouldPreserveDuplicatesWhenFilteringStreamToList() {
// given
var numbersWithDuplicates = Stream.of(1, 2, 2, 3, 3, 3);

// when
var result = FilterUtil.filterToList(numbersWithDuplicates, n -> n >= 2);

// then
assertThat(result).containsExactly(2, 2, 3, 3, 3);
assertThat(result).hasSize(5);
}
}

@Nested
class FilterToStream {
@Test
@DisplayName("Should filter Collection to Stream using predicate")
void shouldFilterCollectionToStreamUsingPredicate() {
// given
var numbers = Arrays.asList(1, 2, 3, 4, 5);

// when
var resultStream = FilterUtil.filterToStream(numbers, n -> n >= 4);

// then
var result = resultStream.toList();
assertThat(result).containsExactly(4, 5);
}

@Test
@DisplayName("Should handle empty Collection when filtering to Stream")
void shouldHandleEmptyCollectionWhenFilteringToStream() {
// given
var emptyList = Collections.<Integer>emptyList();

// when
var resultStream = FilterUtil.filterToStream(emptyList, n -> n > 2);

// then
assertTrue(resultStream.toList().isEmpty());
}

@Test
@DisplayName("Should filter Streamable to Stream using predicate")
void shouldFilterStreamableToStreamUsingPredicate() {
// given
var numbers = Streamable.of(1, 2, 3, 4, 5);

// when
var resultStream = FilterUtil.filterToStream(numbers, n -> n <= 2);

// then
var result = resultStream.toList();
assertThat(result).containsExactly(1, 2);
}

@Test
@DisplayName("Should handle empty Streamable when filtering to Stream")
void shouldHandleEmptyStreamableWhenFilteringToStream() {
// given
var emptyStreamable = Streamable.<Integer>empty();

// when
var resultStream = FilterUtil.filterToStream(emptyStreamable, n -> n > 2);

// then
assertTrue(resultStream.toList().isEmpty());
}

@Test
@DisplayName("Should filter Stream to Stream using predicate")
void shouldFilterStreamToStreamUsingPredicate() {
// given
var numbers = Stream.of(1, 2, 3, 4, 5);

// when
var resultStream = FilterUtil.filterToStream(numbers, n -> n % 2 == 0);

// then
var result = resultStream.toList();
assertThat(result).containsExactly(2, 4);
}

@Test
@DisplayName("Should handle empty Stream when filtering to Stream")
void shouldHandleEmptyStreamWhenFilteringToStream() {
// given
var emptyStream = Stream.<Integer>empty();

// when
var resultStream = FilterUtil.filterToStream(emptyStream, n -> n > 2);

// then
assertTrue(resultStream.toList().isEmpty());
}
}
}