MarkLoveExEx
asked on
Arrays.asList VS ArrayList
I have this cool piece of code that picks out the largest outlier of a bunch of Doubles.
It uses Apache Commons math utilities.
The way "getOutlier" is called is via the following:
But my project has ArrayLists that I need to pass to it.
If I have an ArrayList, how can I call "m.getOutlier", sending it that ArrayList?
I don't want to call m.getOutlier using the "Arrays.asList(blah blah)" like it does now.
I've messed around with this for a few hours, and just can't seem to make the necessary modifications.
I have attached the full code in a file, and here it is here as well:
Thanks.
getOutlier.java
It uses Apache Commons math utilities.
The way "getOutlier" is called is via the following:
MathUtil m = new MathUtil();
Double d0 = (Double) m.getOutlier(Arrays.asList(1.1, 2, 5, 8, 14.6, 3, 4, 3), 0.95);
But my project has ArrayLists that I need to pass to it.
If I have an ArrayList, how can I call "m.getOutlier", sending it that ArrayList?
I don't want to call m.getOutlier using the "Arrays.asList(blah blah)" like it does now.
I've messed around with this for a few hours, and just can't seem to make the necessary modifications.
I have attached the full code in a file, and here it is here as well:
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.commons.math.MathException;
import org.apache.commons.math.distribution.TDistributionImpl;
import org.apache.commons.math.stat.StatUtils;
public class MathUtil {
/** static instance */
private static final MathUtil instance = new MathUtil();
/** default significance level */
public static final double DEFAULT_SIGNIFICANCE_LEVEL = 0.95;
public boolean hasOutlier(Object ... values) {
return hasOutlier(Arrays.asList(values));
}
public boolean hasOutlier(List<?> values) {
return getOutlier(values) != null;
}
/**
* Returns a statistical outlier with the default significance level (0.95),
* or null if no such outlier exists..
*/
public <T> T getOutlier(List<T> values) {
return getOutlier(values, DEFAULT_SIGNIFICANCE_LEVEL);
}
public <T> T getOutlier(List<T> values, double significanceLevel) {
AtomicReference<T> outlier = new AtomicReference<T>();
double grubbs = getGrubbsTestStatistic(values, outlier);
double size = values.size();
if(size < 3) {
return null;
}
TDistributionImpl t = new TDistributionImpl(size - 2.0);
try {
double criticalValue = t.inverseCumulativeProbability((1.0 - significanceLevel) / (2.0 * size));
double criticalValueSquare = criticalValue * criticalValue;
double grubbsCompareValue = ((size - 1) / Math.sqrt(size)) *
Math.sqrt((criticalValueSquare) / (size - 2.0 + criticalValueSquare));
//commented 12/15/2016
// System.out.println("critical value: " + grubbs + " - " + grubbsCompareValue);
if(grubbs > grubbsCompareValue) {
return outlier.get();
} else {
return null;
}
} catch (MathException e) {
throw new RuntimeException(e);
}
}
/** returns a minimum outlier (if one exists) */
public <T> T getOutlierMin(List<T> values) {
T d = getOutlier(values, DEFAULT_SIGNIFICANCE_LEVEL);
if(d == null)
return null;
double d1 = toDouble(d);
double d2 = toDouble(min(values));
if(d1 == d2)
return d;
return null;
}
/** returns a minimum outlier (if one exists) */
public <T> T getOutlierMax(List<T> values) {
T d = getOutlier(values, DEFAULT_SIGNIFICANCE_LEVEL);
if(d == null)
return null;
double d1 = toDouble(d);
double d2 = toDouble(max(values));
if(d1 == d2)
return d;
return null;
}
public <T> double getGrubbsTestStatistic(List<T> values, AtomicReference<T> outlier) {
double[] array = toArray(values);
double mean = StatUtils.mean(array);
double stddev = stdDev(values);
double maxDev = 0;
for(T o : values) {
double d = toDouble(o);
if(Math.abs(mean - d) > maxDev) {
maxDev = Math.abs(mean - d);
outlier.set(o);
}
}
double grubbs = maxDev / stddev;
//commented 12/15/2016
// System.out.println("mean/stddev/maxDev/grubbs: " + mean + " - " + stddev + " - " + maxDev + " - " + grubbs);
return grubbs;
}
private static enum Operator {
MIN, MAX
}
public double sum(Collection<?> c) {
double s = 0;
for(Object o : c) {
s += Double.parseDouble("" + o);
}
return s;
}
public double average(Collection<?> c) {
return sum(c) / (double) c.size();
}
public double avg(Collection<?> c) {
return average(c);
}
public <T> T min(List<T> values) {
return executeOp(values, Operator.MIN);
}
public <T> T max(List<T> values) {
return executeOp(values, Operator.MAX);
}
public double max(double[] values) {
return executeOp(asList(values), Operator.MAX);
}
public int max(int[] values) {
return executeOp(asList(values), Operator.MAX);
}
public long max(long[] values) {
return executeOp(asList(values), Operator.MAX);
}
private <T> T executeOp(List<T> values, Operator op) {
double res = op == Operator.MIN ? Double.MAX_VALUE : Double.MIN_VALUE;
T obj = null;
for(T o : values) {
double d = toDouble(o);
if((op == Operator.MIN && d < res) ||
(op == Operator.MAX && d > res)){
res = d;
obj = o;
}
}
return obj;
}
public List<Integer> asList(int[] values) {
List<Integer> result = new LinkedList<Integer>();
for(int v : values) {
result.add(v);
}
return result;
}
public List<Long> asList(long[] values) {
List<Long> result = new LinkedList<Long>();
for(long v : values) {
result.add(v);
}
return result;
}
public List<Double> asList(double[] values) {
List<Double> result = new LinkedList<Double>();
for(double v : values) {
result.add(v);
}
return result;
}
public Double stdDev(List<?> values) {
return stdDev(toArray(values));
}
public Double stdDev(double[] values) {
return Math.sqrt(StatUtils.variance(values));
}
public Double toDouble(Object o) {
if(o instanceof Double)
return (Double)o;
if(o instanceof Integer)
return (double)(int)(Integer)o;
if(o instanceof Long)
return (double)(long)(Long)o;
return Double.parseDouble("" + o);
}
public List<Double> toDoubles(List<?> values) {
List<Double> d = new LinkedList<Double>();
for(Object o : values) {
double val = toDouble(o);
d.add(val);
}
return d;
}
public double[] toArray(List<?> values) {
double[] d = new double[values.size()];
int count = 0;
for(Object o : values) {
double val = o instanceof Double ? (Double)o : Double.parseDouble("" + o);
d[count++] = val;
}
return d;
}
public Integer toInteger(String in) {
if(in == null)
return null;
try {
return Integer.parseInt(in);
} catch(Exception e) {
return null;
}
}
public static MathUtil getInstance() {
// System.out.println(Thread.currentThread().toString() + "-" + Thread.currentThread().getId() + " - " +
// "MathUtil.getInstance()");
return instance;
}
private static void assertion(boolean value) {
if(!value)
throw new RuntimeException("Assertion failed.");
}
public static void main(String[] args) {
//MY QUESTION FOR EXPERTS-EXCHANGE:
//If I have an ArrayList, how can I call "m.getOutlier", sending it that ArrayList?
//I don't want to call m.getOutlier using the "Arrays.asList(blah blah)" like it does now
MathUtil m = new MathUtil();
Double d0 = (Double) m.getOutlier(Arrays.asList(1.1, 2, 5, 8, 14.6, 3, 4, 3), 0.95);
System.out.println(d0);
}
}
Thanks.
getOutlier.java
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
See comment. :)
Depending on exactly what type your "myObsArrayList" is, if you can't just pass it directly (because it's not a List<Double> type) you at least shouldn't have needed to go to quite the lengths you detailed above, definitely shouldn't need the DefaultListModel stuff. Something like the below should have been enough to get you going (and get rid of your warning)...
List<Double> myList = new ArrayList<Double>();
for (Object value : myObsArrayList) { // Or however you looped through your original array (i.e. exactly the same loop as in step 3 above)
myList.add(value); // The myList.add is right, but change the value you are passing it to, again, whatever you did in step 3
}
Double d0 = m.getOutlier(myList, 0.95); // No casts should be necessary, and no warnings should be given
ASKER
1.) Create a new ArrayList<Double> (called myArrayList)
2.) Create a new DefaultListModel<Double> (called myListModel)
3.) Loop through my other (not shown) ArrayList (called myObsArrayList) that contains the data I need, and addElement to the myListModel
4.) Then, myArrayList = Collections.list(myListMod
5.) Finally, Double d0 = (Double) m.getOutlier((List) myArrayList, 0.95);
Whew.
I'm still getting a warning on step 5, which says, "Type safety: Unchecked invocation getOutlier(List, double) of the generic method getOutlier(List<T>,double)
But, it still seemed to run ok.
By your suggestion (to pass a List<Double>), I did the casting on Step 5 above, and worked backwards. I appreciate it.