chore/feat: add stream operations to PlotQuery, avoid larger lookups

This commit is contained in:
Pierre Maurice Schwang 2025-02-22 21:27:58 +01:00
parent 3f573b4d46
commit 424806c5f4
No known key found for this signature in database
GPG Key ID: 37E613079F3E5BB9
8 changed files with 92 additions and 16 deletions

View File

@ -24,6 +24,7 @@ import com.plotsquared.core.plot.PlotArea;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Stream;
class AreaLimitedPlotProvider implements PlotProvider {
@ -42,4 +43,9 @@ class AreaLimitedPlotProvider implements PlotProvider {
return plots;
}
@Override
public Stream<Plot> streamPlots() {
return streamPlotsInPlotAreas(this.areas.toArray(PlotArea[]::new));
}
}

View File

@ -22,6 +22,7 @@ import com.plotsquared.core.PlotSquared;
import com.plotsquared.core.plot.Plot;
import java.util.Collection;
import java.util.stream.Stream;
class ExpiredPlotProvider implements PlotProvider {
@ -30,4 +31,9 @@ class ExpiredPlotProvider implements PlotProvider {
return PlotSquared.platform().expireManager().getPendingExpired();
}
@Override
public Stream<Plot> streamPlots() {
return getPlots().stream();
}
}

View File

@ -23,6 +23,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.Collection;
import java.util.Collections;
import java.util.stream.Stream;
class FixedPlotProvider implements PlotProvider {
@ -37,4 +38,9 @@ class FixedPlotProvider implements PlotProvider {
return Collections.singleton(plot);
}
@Override
public Stream<Plot> streamPlots() {
return Stream.of(plot);
}
}

View File

@ -26,6 +26,7 @@ import org.checkerframework.checker.nullness.qual.NonNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Stream;
class GlobalPlotProvider implements PlotProvider {
@ -44,4 +45,9 @@ class GlobalPlotProvider implements PlotProvider {
return plots;
}
@Override
public Stream<Plot> streamPlots() {
return streamPlotsInPlotAreas(this.plotAreaManager.getAllPlotAreas());
}
}

View File

@ -22,6 +22,7 @@ import com.plotsquared.core.plot.Plot;
import java.util.Collection;
import java.util.Collections;
import java.util.stream.Stream;
class NullProvider implements PlotProvider {
@ -30,4 +31,9 @@ class NullProvider implements PlotProvider {
return Collections.emptyList();
}
@Override
public Stream<Plot> streamPlots() {
return Stream.empty();
}
}

View File

@ -19,12 +19,44 @@
package com.plotsquared.core.util.query;
import com.plotsquared.core.plot.Plot;
import com.plotsquared.core.plot.PlotArea;
import java.util.Collection;
import java.util.Iterator;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
@FunctionalInterface
interface PlotProvider {
Collection<Plot> getPlots();
Stream<Plot> streamPlots();
default Stream<Plot> streamPlotsInPlotAreas(PlotArea[] areas) {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(new Iterator<>() {
private int areaIndex = -1;
private Iterator<Plot> currentAreaPlots;
@Override
public boolean hasNext() {
if (currentAreaPlots == null) {
return areas.length > 0;
}
if (!currentAreaPlots.hasNext()) {
return ++areaIndex < areas.length - 1;
}
return true;
}
@Override
public Plot next() {
if (currentAreaPlots == null) {
currentAreaPlots = areas[++areaIndex].getPlots().iterator();
}
return currentAreaPlots.next();
}
}, Spliterator.IMMUTABLE), false);
}
}

View File

@ -229,6 +229,7 @@ public final class PlotQuery implements Iterable<Plot> {
public @NonNull PlotQuery hasOwner() {
return this.addFilter(new HasOwnerFilter());
}
/**
* Query for plots with a specific alias
*
@ -307,7 +308,7 @@ public final class PlotQuery implements Iterable<Plot> {
* @return Matching plots
*/
public @NonNull Stream<Plot> asStream() {
return this.asList().stream();
return this.asList().stream(); // TODO: use stream functionality from PlotProvider?
}
/**
@ -427,22 +428,29 @@ public final class PlotQuery implements Iterable<Plot> {
* @return {@code true} if any provided plot matches the filters.
*/
public boolean anyMatch() {
if (this.filters.isEmpty()) {
return !this.plotProvider.getPlots().isEmpty();
} else {
final Collection<Plot> plots = this.plotProvider.getPlots();
outer:
for (final Plot plot : plots) {
// a plot must pass all filters to match the criteria
for (final PlotFilter filter : this.filters) {
if (!filter.accepts(plot)) {
continue outer;
}
return hasMinimumMatches(1);
}
/**
* Get whether this query matches at least {@code minimum} plots.
* <br />
* Should be prioritized over {@link #count()}, if possible.
* This method only queries as many plots and areas as required without applying sorting. (short-circuiting on the stream)
*
* @param minimum the minimum amount of matches plots expected (inclusive)
* @return {@code true} if this query's result contains at least {@code minimum} plots (after optional filters).
*
* @since TODO
*/
public boolean hasMinimumMatches(int minimum) {
return this.plotProvider.streamPlots().filter(plot -> {
for (final PlotFilter filter : filters) {
if (!filter.accepts(plot)) {
return false;
}
return true; // a plot passed all filters, so we have a match
}
return false;
}
return true;
}).limit(minimum).count() == minimum;
}
@NonNull

View File

@ -31,6 +31,7 @@ import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
class SearchPlotProvider implements PlotProvider {
@ -115,4 +116,9 @@ class SearchPlotProvider implements PlotProvider {
return getPlotsBySearch(this.searchTerm);
}
@Override
public Stream<Plot> streamPlots() {
return getPlots().stream(); // TODO: look into potentially optimizations here?
}
}