📄 dynamictimeseriescollection.java
字号:
/* ===========================================================
* JFreeChart : a free chart library for the Java(tm) platform
* ===========================================================
*
* (C) Copyright 2000-2007, by Object Refinery Limited and Contributors.
*
* Project Info: http://www.jfree.org/jfreechart/index.html
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*
* [Java is a trademark or registered trademark of Sun Microsystems, Inc.
* in the United States and other countries.]
*
* --------------------------------
* DynamicTimeSeriesCollection.java
* --------------------------------
* (C) Copyright 2002-2007, by I. H. Thomae and Contributors.
*
* Original Author: I. H. Thomae (ithomae@ists.dartmouth.edu);
* Contributor(s): David Gilbert (for Object Refinery Limited);
*
* Changes
* -------
* 22-Nov-2002 : Initial version completed
* Jan 2003 : Optimized advanceTime(), added implemnt'n of RangeInfo intfc
* (using cached values for min, max, and range); also added
* getOldestIndex() and getNewestIndex() ftns so client classes
* can use this class as the master "index authority".
* 22-Jan-2003 : Made this class stand on its own, rather than extending
* class FastTimeSeriesCollection
* 31-Jan-2003 : Changed TimePeriod --> RegularTimePeriod (DG);
* 13-Mar-2003 : Moved to com.jrefinery.data.time package (DG);
* 29-Apr-2003 : Added small change to appendData method, from Irv Thomae (DG);
* 19-Sep-2003 : Added new appendData method, from Irv Thomae (DG);
* 05-May-2004 : Now extends AbstractIntervalXYDataset. This also required a
* change to the return type of the getY() method - I'm slightly
* unsure of the implications of this, so it might require some
* further amendment (DG);
* 15-Jul-2004 : Switched getX() with getXValue() and getY() with
* getYValue() (DG);
* 11-Jan-2004 : Removed deprecated code in preparation for the 1.0.0
* release (DG);
* 02-Feb-2007 : Removed author tags all over JFreeChart sources (DG);
*
*/
package org.jfree.data.time;
import java.util.Calendar;
import java.util.TimeZone;
import org.jfree.data.DomainInfo;
import org.jfree.data.Range;
import org.jfree.data.RangeInfo;
import org.jfree.data.general.SeriesChangeEvent;
import org.jfree.data.xy.AbstractIntervalXYDataset;
import org.jfree.data.xy.IntervalXYDataset;
/**
* A dynamic dataset.
* <p>
* Like FastTimeSeriesCollection, this class is a functional replacement
* for JFreeChart's TimeSeriesCollection _and_ TimeSeries classes.
* FastTimeSeriesCollection is appropriate for a fixed time range; for
* real-time applications this subclass adds the ability to append new
* data and discard the oldest.
* In this class, the arrays used in FastTimeSeriesCollection become FIFO's.
* NOTE:As presented here, all data is assumed >= 0, an assumption which is
* embodied only in methods associated with interface RangeInfo.
*/
public class DynamicTimeSeriesCollection extends AbstractIntervalXYDataset
implements IntervalXYDataset,
DomainInfo,
RangeInfo {
/**
* Useful constant for controlling the x-value returned for a time
* period.
*/
public static final int START = 0;
/**
* Useful constant for controlling the x-value returned for a time period.
*/
public static final int MIDDLE = 1;
/**
* Useful constant for controlling the x-value returned for a time period.
*/
public static final int END = 2;
/** The maximum number of items for each series (can be overridden). */
private int maximumItemCount = 2000; // an arbitrary safe default value
/** The history count. */
protected int historyCount;
/** Storage for the series keys. */
private Comparable[] seriesKeys;
/** The time period class - barely used, and could be removed (DG). */
private Class timePeriodClass = Minute.class; // default value;
/** Storage for the x-values. */
protected RegularTimePeriod[] pointsInTime;
/** The number of series. */
private int seriesCount;
/**
* A wrapper for a fixed array of float values.
*/
protected class ValueSequence {
/** Storage for the float values. */
float[] dataPoints;
/**
* Default constructor:
*/
public ValueSequence() {
this(DynamicTimeSeriesCollection.this.maximumItemCount);
}
/**
* Creates a sequence with the specified length.
*
* @param length the length.
*/
public ValueSequence(int length) {
this.dataPoints = new float[length];
for (int i = 0; i < length; i++) {
this.dataPoints[i] = 0.0f;
}
}
/**
* Enters data into the storage array.
*
* @param index the index.
* @param value the value.
*/
public void enterData(int index, float value) {
this.dataPoints[index] = value;
}
/**
* Returns a value from the storage array.
*
* @param index the index.
*
* @return The value.
*/
public float getData(int index) {
return this.dataPoints[index];
}
}
/** An array for storing the objects that represent each series. */
protected ValueSequence[] valueHistory;
/** A working calendar (to recycle) */
protected Calendar workingCalendar;
/**
* The position within a time period to return as the x-value (START,
* MIDDLE or END).
*/
private int position;
/**
* A flag that indicates that the domain is 'points in time'. If this flag
* is true, only the x-value is used to determine the range of values in
* the domain, the start and end x-values are ignored.
*/
private boolean domainIsPointsInTime;
/** index for mapping: points to the oldest valid time & data. */
private int oldestAt; // as a class variable, initializes == 0
/** Index of the newest data item. */
private int newestAt;
// cached values used for interface DomainInfo:
/** the # of msec by which time advances. */
private long deltaTime;
/** Cached domain start (for use by DomainInfo). */
private Long domainStart;
/** Cached domain end (for use by DomainInfo). */
private Long domainEnd;
/** Cached domain range (for use by DomainInfo). */
private Range domainRange;
// Cached values used for interface RangeInfo: (note minValue pinned at 0)
// A single set of extrema covers the entire SeriesCollection
/** The minimum value. */
private Float minValue = new Float(0.0f);
/** The maximum value. */
private Float maxValue = null;
/** The value range. */
private Range valueRange; // autoinit's to null.
/**
* Constructs a dataset with capacity for N series, tied to default
* timezone.
*
* @param nSeries the number of series to be accommodated.
* @param nMoments the number of TimePeriods to be spanned.
*/
public DynamicTimeSeriesCollection(int nSeries, int nMoments) {
this(nSeries, nMoments, new Millisecond(), TimeZone.getDefault());
this.newestAt = nMoments - 1;
}
/**
* Constructs an empty dataset, tied to a specific timezone.
*
* @param nSeries the number of series to be accommodated
* @param nMoments the number of TimePeriods to be spanned
* @param zone the timezone.
*/
public DynamicTimeSeriesCollection(int nSeries, int nMoments,
TimeZone zone) {
this(nSeries, nMoments, new Millisecond(), zone);
this.newestAt = nMoments - 1;
}
/**
* Creates a new dataset.
*
* @param nSeries the number of series.
* @param nMoments the number of items per series.
* @param timeSample a time period sample.
*/
public DynamicTimeSeriesCollection(int nSeries,
int nMoments,
RegularTimePeriod timeSample) {
this(nSeries, nMoments, timeSample, TimeZone.getDefault());
}
/**
* Creates a new dataset.
*
* @param nSeries the number of series.
* @param nMoments the number of items per series.
* @param timeSample a time period sample.
* @param zone the time zone.
*/
public DynamicTimeSeriesCollection(int nSeries,
int nMoments,
RegularTimePeriod timeSample,
TimeZone zone) {
// the first initialization must precede creation of the ValueSet array:
this.maximumItemCount = nMoments; // establishes length of each array
this.historyCount = nMoments;
this.seriesKeys = new Comparable[nSeries];
// initialize the members of "seriesNames" array so they won't be null:
for (int i = 0; i < nSeries; i++) {
this.seriesKeys[i] = "";
}
this.newestAt = nMoments - 1;
this.valueHistory = new ValueSequence[nSeries];
this.timePeriodClass = timeSample.getClass();
/// Expand the following for all defined TimePeriods:
if (this.timePeriodClass == Second.class) {
this.pointsInTime = new Second[nMoments];
}
else if (this.timePeriodClass == Minute.class) {
this.pointsInTime = new Minute[nMoments];
}
else if (this.timePeriodClass == Hour.class) {
this.pointsInTime = new Hour[nMoments];
}
/// .. etc....
this.workingCalendar = Calendar.getInstance(zone);
this.position = START;
this.domainIsPointsInTime = true;
}
/**
* Fill the pointsInTime with times using TimePeriod.next():
* Will silently return if the time array was already populated.
*
* Also computes the data cached for later use by
* methods implementing the DomainInfo interface:
*
* @param start the start.
*
* @return ??.
*/
public synchronized long setTimeBase(RegularTimePeriod start) {
if (this.pointsInTime[0] == null) {
this.pointsInTime[0] = start;
for (int i = 1; i < this.historyCount; i++) {
this.pointsInTime[i] = this.pointsInTime[i - 1].next();
}
}
long oldestL = this.pointsInTime[0].getFirstMillisecond(
this.workingCalendar
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -