All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.espertech.esper.collection.SortedDoubleVector Maven / Gradle / Ivy

/*
 ***************************************************************************************
 *  Copyright (C) 2006 EsperTech, Inc. All rights reserved.                            *
 *  http://www.espertech.com/esper                                                     *
 *  http://www.espertech.com                                                           *
 *  ---------------------------------------------------------------------------------- *
 *  The software in this package is published under the terms of the GPL license       *
 *  a copy of which has been included with this distribution in the license.txt file.  *
 ***************************************************************************************
 */
package com.espertech.esper.collection;

import java.util.ArrayList;

/**
 * Sorted, reference-counting set based on an ArrayList implementation that it being kept sorted.
 */
public class SortedDoubleVector {
    private ArrayList values;

    /**
     * Constructor.
     */
    public SortedDoubleVector() {
        values = new ArrayList();
    }

    public SortedDoubleVector(ArrayList values) {
        this.values = values;
    }

    /**
     * Clear out the collection.
     */
    public void clear() {
        values.clear();
    }

    /**
     * Returns the number of items in the collection.
     *
     * @return size
     */
    public int size() {
        return values.size();
    }

    /**
     * Returns the value at a given index.
     *
     * @param index for which to return value for
     * @return value at index
     */
    public double getValue(int index) {
        return values.get(index);
    }

    /**
     * Add a value to the collection.
     *
     * @param value is the double-type value to add
     */
    public void add(double value) {
        if (Double.isNaN(value)) {
            return;
        }

        int index = findInsertIndex(value);

        if (index == -1) {
            values.add(value);
        } else {
            values.add(index, value);
        }
    }

    /**
     * Remove a value from the collection.
     *
     * @param value to remove
     * @throws IllegalStateException if the value has not been added
     */
    public void remove(double value) {
        if (Double.isNaN(value)) {
            return;
        }

        int index = findInsertIndex(value);
        if (index == -1) {
            throw new IllegalStateException("Value not found in collection");
        }
        Double valueAtIndex = values.get(index);
        if ((valueAtIndex != null) && (!valueAtIndex.equals(value))) {
            throw new IllegalStateException("Value not found in collection");
        }
        values.remove(index);
    }

    /**
     * Returns underlying ArrayList, for testing purposes only.
     *
     * @return sorted double values list
     */
    public ArrayList getValues() {
        return values;
    }

    /**
     * Returns the index into which to insert to.
     * Proptected access level for convenient testing.
     *
     * @param value to find insert index
     * @return position to insert the value to, or -1 to indicate to add to the end.
     */
    protected int findInsertIndex(double value) {
        if (values.size() > 2) {
            int startIndex = values.size() >> 1;
            double startValue = values.get(startIndex);
            int insertAt;

            if (value < startValue) {
                // find in lower half
                insertAt = findInsertIndex(0, startIndex - 1, value);
            } else if (value > startValue) {
                // find in upper half
                insertAt = findInsertIndex(startIndex + 1, values.size() - 1, value);
            } else {
                // we hit the value
                insertAt = startIndex;
            }

            if (insertAt == values.size()) {
                return -1;
            }
            return insertAt;
        }

        if (values.size() == 2) {
            if (value > values.get(1)) {
                return -1;
            } else if (value <= values.get(0)) {
                return 0;
            } else {
                return 1;
            }
        }

        if (values.size() == 1) {
            if (value > values.get(0)) {
                return -1;
            } else {
                return 0;
            }
        }

        return -1;
    }

    private int findInsertIndex(int lowerBound, int upperBound, double value) {
        while (true) {
            if (upperBound == lowerBound) {
                double valueLowerBound = values.get(lowerBound);
                if (value <= valueLowerBound) {
                    return lowerBound;
                } else {
                    return lowerBound + 1;
                }
            }

            if (upperBound - lowerBound == 1) {
                double valueLowerBound = values.get(lowerBound);
                if (value <= valueLowerBound) {
                    return lowerBound;
                }

                double valueUpperBound = values.get(upperBound);
                if (value > valueUpperBound) {
                    return upperBound + 1;
                }

                return upperBound;
            }

            int nextMiddle = lowerBound + ((upperBound - lowerBound) >> 1);
            double valueAtMiddle = values.get(nextMiddle);

            if (value < valueAtMiddle) {
                // find in lower half
                upperBound = nextMiddle - 1;
            } else if (value > valueAtMiddle) {
                // find in upper half
                lowerBound = nextMiddle;
            } else {
                return nextMiddle;
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy