Skip to content

Instantly share code, notes, and snippets.

@ParadoxV5
Last active November 11, 2022 05:23
Show Gist options
  • Save ParadoxV5/db5678fb6e4d99873624c261ca920c0d to your computer and use it in GitHub Desktop.
Save ParadoxV5/db5678fb6e4d99873624c261ca920c0d to your computer and use it in GitHub Desktop.
Strategies to search the element(s) in a Java Collection that the given non-`null` item `equals` while not necessarily be the same object (i.e. equal by `==`) (returns `null` for single-search and empty collection for “all”-search) [WTFPL License]
package xyz.paradoxv5.java;
import java.util.*;
import org.jetbrains.annotations.*;
/**
For {@code List}s, there is also {@link List#indexOf(Object)} + {@link List#get}.
For <b>sorted</b> Arrays and {@code List}s, Java has
{@link Arrays#binarySearch(Object[], Object)} and
{@link Collections#binarySearch(List, Object) respectively}
*/
public class CollectionSearch {
/** Linear Search – There aren’t many other options for most arbitrary {@link Collection} */
public static <E> @Nullable E find(@NotNull Collection<E> collection, @NotNull E o) {
Objects.requireNonNull(o);
return collection.parallelStream().filter(o::equals).findAny().orElse(null);
}
/**
{@link SortedSet}s are pre-sorted and makes searching simply a couple of splitting steps.
Note that unlike {@link NavigableSet},
{@code SortedSet} does not support closed ranges that don’t exclude their boundaries.
As there is no telling of a next larger or previous smaller for an arbitrary element type,
it needs some post-filter processing to fetch the actual target element (or report {@code null}.
*/
public static <E> @Nullable E find(@NotNull SortedSet<E> set, @NotNull E o) {
SortedSet<E> tailSet = set.tailSet(Objects.requireNonNull(o)); // View of elements that are ≥ `o`
// Can also clone the set but with the comparator reversed to `tailSet` for elements ≤ `o`, but that’s inefficient
if(tailSet.isEmpty()) // catch `NoSuchElementException` from upcoming `tailSet.first()`
return null;
E firstOfTail = tailSet.first();
return o.equals(firstOfTail) ? firstOfTail : null;
}
/**
The {@code NavigableSet} (subclass of {@link SortedSet}) has an all-in-one
{@link NavigableSet#subSet(Object, boolean, Object, boolean)}
method that can split directly to just the target element remaining.
Setting both booleans to {@code true} filters out elements that are
either lower or greater than (i.e., not equal to) the given object.
*/
public static <E> @Nullable E find(@NotNull NavigableSet<E> set, @NotNull E o) {
return set.subSet(Objects.requireNonNull(o), true, o, true).pollFirst();
}
/** No instantiating */
private CollectionSearch() {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment