Last active
November 11, 2022 05:23
-
-
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]
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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