001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.math.stat.descriptive;
018
019 import java.io.Serializable;
020 import java.util.ArrayList;
021 import java.util.List;
022
023 import org.apache.commons.math.MathException;
024 import org.apache.commons.math.stat.descriptive.UnivariateStatistic;
025 import org.apache.commons.math.stat.descriptive.DescriptiveStatistics;
026 import org.apache.commons.math.util.DefaultTransformer;
027 import org.apache.commons.math.util.NumberTransformer;
028
029 /**
030 * @version $Revision: 762087 $ $Date: 2009-04-05 10:20:18 -0400 (Sun, 05 Apr 2009) $
031 */
032 public class ListUnivariateImpl extends DescriptiveStatistics implements Serializable {
033
034 /** Serializable version identifier */
035 private static final long serialVersionUID = -8837442489133392138L;
036
037 /**
038 * Holds a reference to a list - GENERICs are going to make
039 * our lives easier here as we could only accept List<Number>
040 */
041 protected List<Object> list;
042
043 /** Number Transformer maps Objects to Number for us. */
044 protected NumberTransformer transformer;
045
046 /**
047 * No argument Constructor
048 */
049 public ListUnivariateImpl(){
050 this(new ArrayList<Object>());
051 }
052
053 /**
054 * Construct a ListUnivariate with a specific List.
055 * @param list The list that will back this DescriptiveStatistics
056 */
057 public ListUnivariateImpl(List<Object> list) {
058 this(list, new DefaultTransformer());
059 }
060
061 /**
062 * Construct a ListUnivariate with a specific List.
063 * @param list The list that will back this DescriptiveStatistics
064 * @param transformer the number transformer used to convert the list items.
065 */
066 public ListUnivariateImpl(List<Object> list, NumberTransformer transformer) {
067 super();
068 this.list = list;
069 this.transformer = transformer;
070 }
071
072 /** {@inheritDoc} */
073 @Override
074 public double[] getValues() {
075
076 int length = list.size();
077
078 // If the window size is not INFINITE_WINDOW AND
079 // the current list is larger that the window size, we need to
080 // take into account only the last n elements of the list
081 // as definied by windowSize
082
083 if (windowSize != DescriptiveStatistics.INFINITE_WINDOW &&
084 windowSize < list.size())
085 {
086 length = list.size() - Math.max(0, list.size() - windowSize);
087 }
088
089 // Create an array to hold all values
090 double[] copiedArray = new double[length];
091
092 for (int i = 0; i < copiedArray.length; i++) {
093 copiedArray[i] = getElement(i);
094 }
095 return copiedArray;
096 }
097
098 /** {@inheritDoc} */
099 @Override
100 public double getElement(int index) {
101
102 double value = Double.NaN;
103
104 int calcIndex = index;
105
106 if (windowSize != DescriptiveStatistics.INFINITE_WINDOW &&
107 windowSize < list.size())
108 {
109 calcIndex = (list.size() - windowSize) + index;
110 }
111
112
113 try {
114 value = transformer.transform(list.get(calcIndex));
115 } catch (MathException e) {
116 e.printStackTrace();
117 }
118
119 return value;
120 }
121
122 /** {@inheritDoc} */
123 @Override
124 public long getN() {
125 int n = 0;
126
127 if (windowSize != DescriptiveStatistics.INFINITE_WINDOW) {
128 if (list.size() > windowSize) {
129 n = windowSize;
130 } else {
131 n = list.size();
132 }
133 } else {
134 n = list.size();
135 }
136 return n;
137 }
138
139 /** {@inheritDoc} */
140 @Override
141 public void addValue(double v) {
142 list.add(Double.valueOf(v));
143 }
144
145 /**
146 * Adds an object to this list.
147 * @param o Object to add to the list
148 */
149 public void addObject(Object o) {
150 list.add(o);
151 }
152
153 /**
154 * Clears all statistics.
155 * <p>
156 * <strong>N.B.: </strong> This method has the side effect of clearing the underlying list.
157 */
158 @Override
159 public void clear() {
160 list.clear();
161 }
162
163 /**
164 * Apply the given statistic to this univariate collection.
165 * @param stat the statistic to apply
166 * @return the computed value of the statistic.
167 */
168 @Override
169 public double apply(UnivariateStatistic stat) {
170 double[] v = this.getValues();
171
172 if (v != null) {
173 return stat.evaluate(v, 0, v.length);
174 }
175 return Double.NaN;
176 }
177
178 /**
179 * Access the number transformer.
180 * @return the number transformer.
181 */
182 public NumberTransformer getTransformer() {
183 return transformer;
184 }
185
186 /**
187 * Modify the number transformer.
188 * @param transformer the new number transformer.
189 */
190 public void setTransformer(NumberTransformer transformer) {
191 this.transformer = transformer;
192 }
193
194 /** {@inheritDoc} */
195 @Override
196 public synchronized void setWindowSize(int windowSize) {
197 this.windowSize = windowSize;
198 //Discard elements from the front of the list if the windowSize is less than
199 // the size of the list.
200 int extra = list.size() - windowSize;
201 for (int i = 0; i < extra; i++) {
202 list.remove(0);
203 }
204 }
205
206 /** {@inheritDoc} */
207 @Override
208 public synchronized int getWindowSize() {
209 return windowSize;
210 }
211
212 }