org.neo4j.cypher.internal.collection.DefaultComparatorTopTable Maven / Gradle / Ivy
/*
* Copyright (c) "Neo4j"
* Neo4j Sweden AB [https://neo4j.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.neo4j.cypher.internal.collection;
import static org.neo4j.memory.HeapEstimator.shallowSizeOfInstance;
import static org.neo4j.util.Preconditions.checkArgument;
import java.util.Comparator;
import java.util.Iterator;
import org.neo4j.exceptions.CypherExecutionException;
import org.neo4j.memory.EmptyMemoryTracker;
import org.neo4j.memory.MemoryTracker;
/**
* The default implementation of a Top N table used by all runtimes
*
* It accepts tuples as boxed objects that implements Comparable
*
* Implements the following interface:
* (since the code is generated it does not actually need to declare it with implements)
*
* public interface SortTable
* {
* boolean add( T e );
*
* void sort();
*
* Iterator iterator();
* }
*
* Uses a max heap to collect a maximum of {@code totalCount} tuples in reverse order.
* When sort() is called, it does a heap sort in-place which will reverse the order
* again, resulting in a fully sorted array which the iterator will go through.
*/
public class DefaultComparatorTopTable extends MemoryTrackingHeap
implements Iterable // implements SortTable
{
private static final long SHALLOW_INSTANCE_SIZE = shallowSizeOfInstance(DefaultComparatorTopTable.class);
private long totalCount;
private boolean heapified;
private boolean isSorted;
public DefaultComparatorTopTable(Comparator super T> comparator, long totalCount) {
this(comparator, totalCount, EmptyMemoryTracker.INSTANCE);
}
public DefaultComparatorTopTable(Comparator super T> comparator, long totalCount, MemoryTracker memoryTracker) {
this(comparator, totalCount, memoryTracker, 0L);
}
public DefaultComparatorTopTable(
Comparator super T> comparator, long totalCount, MemoryTracker memoryTracker, long extraShallowSize) {
super(comparator, (int) Math.min(totalCount, 1024), memoryTracker, SHALLOW_INSTANCE_SIZE + extraShallowSize);
this.totalCount = totalCount;
}
public boolean add(T e) {
T evicted = addAndGetEvicted(e);
return e != evicted;
}
public T addAndGetEvicted(T e) {
if (size < totalCount) {
if (size >= heap.length) {
grow(size + 1);
}
heap[size++] = e;
return null;
} else {
if (!heapified) {
heapify();
heapified = true;
}
return super.replace(e);
}
}
public int getSize() {
return size;
}
/**
* Returns the top totalCount
elements, but in no particular order
*/
public Iterator unorderedIterator() {
return getIterator();
}
/**
* Must call before calling iterator()
.
*/
@Override
public void sort() {
if (isSorted) {
return;
}
if (!heapified) {
java.util.Arrays.sort(heap, 0, size, comparator);
} else {
// Heap sort the array
super.sort();
}
isSorted = true;
}
public void reset(long newTotalCount) {
checkArgument(newTotalCount > 0, "Top table size must be greater than 0");
totalCount = newTotalCount;
clear();
heapified = false;
isSorted = false;
}
/**
* Must call after calling sort()
.
*/
@Override
public Iterator iterator() {
if (!isSorted) {
// This should never happen in generated code but is here to simplify debugging if used incorrectly
throw new IllegalStateException("sort() needs to be called before requesting an iterator");
}
return getIterator();
}
/**
* Create an iterator that will automatically call close() when it is exhausted.
* The caller can also provide an optional closeable of its own that will also be closed.
* Must call after calling sort()
.
*/
public Iterator autoClosingIterator(AutoCloseable closeable) {
if (!isSorted) {
// This should never happen in generated code but is here to simplify debugging if used incorrectly
throw new IllegalStateException("sort() needs to be called before requesting an iterator");
}
return getAutoClosingIterator(closeable);
}
@Override
protected void overflow(long maxSize) {
throw new CypherExecutionException("Top table cannot hold more than " + maxSize + " elements.");
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy