Java multithreading, accessing list from separate classes - java

Just to start off, I'm pretty inept at Java and especially multithreading, so what I'm asking might sound a bit ordinary. I am attempting to create a program in which I create three threads which each accomplish the specific task of depicting certain values between ten integers, such as average, deviation, etc. How would I approach this?
I am attempting to create four classes, one for the main program, and three for each of the calculations of the values between each: class "Average" for the average of the ten numbers in the array, class "Median" for the median, etc. The code for the other 3 classes I can easily write, no problem there. My main problem is that since the list "integers" is not available outside the class, I can't write the code for finding each of the values I need in the three programs.
Is there a better way to write this so I can actually access the list from inside the classes for each of the threads?
import java.util.*;
public class ThreadDemo
{
public static void main(String[] args)
{
Random number = new Random();
List integers = new ArrayList();
for (int i = 0; i < 10; i++)
{
integers.add(number.nextInt(101));
}
Thread average = new Thread(new Average());
Thread median = new Thread(new Median());
Thread deviation = new Thread(new Deviation());
average.start();
median.start();
deviation.start();
}
}
class Average extends Thread
{
public void run()
{
// code for finding average
}
}
class Median extends Thread
{
public void run()
{
// code for finding median
}
}
class Deviation extends Thread
{
public void run()
{
// code for finding deviation
}
}

There are a lot of options to achieve what you are trying to do. I will outline two:
each computation method implementing the Callable interface and taking data into the instance constructor;
each computation method implementing the Function interface and passing data into the call via the closure.
It is generally advisable to program to interfaces, that is require an interface as method argument. All below examples follow this by implementing Callable or Function and working with those high level interfaces elsewhere. The code for both cases looks very similar with the main difference being the remapping of Function to Callable in the latter case using the closure state.
Let's start with some common utilities (statics for brevity only):
The following method will create a Collection of 100 random integers in [0,100]:
private static Collection<Integer> ints() {
Random random = new Random();
return random.ints(100, 0, 100)
.boxed()
.collect(Collectors.toList());
}
The following method will execute a collection of Callables concurrently on a cached executor pool. Each callable is generic and will deliver a double value. Those values (in random order) will be collected and returned as a list:
private static List<Double> concurrently(Collection<Callable<Double>> callables) throws InterruptedException, ExecutionException {
ExecutorService executors = Executors.newCachedThreadPool();
Collection<Future<Double>> futures = executors.invokeAll(callables);
List<Double> res = new ArrayList<>();
for (Future<Double> future: futures) {
res.add(future.get());
}
executors.shutdownNow();
return res;
}
Now let's get back to the core logic.
Case 1: Implementing Callable
class Averager<V extends Number> implements Callable<Double> {
private final Collection<V> values = new ArrayList<>();
Averager(Collection<V> values) {
this.values.addAll(values);
}
#Override
public Double call() {
double sum = 0.0;
for (V value : values) {
sum += value.doubleValue();
}
return Double.valueOf(sum / values.size());
}
}
class Medianer<V extends Number> implements Callable<Double> {
private final Collection<V> values = new ArrayList<>();
Medianer(Collection<V> values) {
this.values.addAll(values);
}
#Override
public Double call() {
List<V> sorted = new ArrayList<>(values);
sorted.sort(Comparator.comparingDouble(Number::doubleValue));
// TODO treat odd/even number of elements separately
return Double.valueOf(sorted.get(sorted.size() / 2).doubleValue());
}
}
Note: whenever you take a collection as a constructor argument, do not store the reference to the original collection provided in a private field, copy values. If collections are very large, do not pass them to constructor or make unmodifiable.
#Test
public void usingCallable() throws InterruptedException, ExecutionException {
Collection<Integer> values = ints();
Collection<Callable<Double>> callables = new ArrayList<>();
callables.add(new Averager<>(values));
callables.add(new Medianer<>(values));
List<Double> res = concurrently(callables);
System.out.println(res);
}
Case 2: Implementing Function
class Averager<V extends Number> implements Function<Collection<V>, Double> {
#Override
public Double apply(Collection<V> values) {
double sum = 0.0;
for (V value : values) {
sum += value.doubleValue();
}
return Double.valueOf(sum / values.size());
}
}
class Medianer<V extends Number> implements Function<Collection<V>, Double> {
#Override
public Double apply(Collection<V> values) {
List<V> sorted = new ArrayList<>(values);
sorted.sort(Comparator.comparingDouble(Number::doubleValue));
// TODO treat odd/even number of elements separately
return Double.valueOf(sorted.get(sorted.size() / 2).doubleValue());
}
}
#Test
public void usingFunction() throws InterruptedException, ExecutionException {
Collection<Integer> values = ints();
Collection<Function<Collection<Integer>, Double>> functions = new ArrayList<>();
functions.add(new Averager<>());
functions.add(new Medianer<>());
List<Callable<Double>> callables = functions.stream().map(f -> (Callable<Double>) () -> f.apply(values)).collect(Collectors.toList());
List<Double> res = concurrently(callables);
System.out.println(res);
}
I personally prefer the latter one because your computation methods become generic functions, that is implementing the generic Function interface and can be used in other contexts.
Reworking case 1 and 2 with lambdas
You can do some interesting things with lambdas here. For the case of functions, you can just predefine them as lambdas instead of constructing new instances of specifically defined class:
static final Function<Collection<Integer>, Double> averager = (values) -> {
double sum = 0.0;
for (Integer value : values) {
sum += value.doubleValue();
}
return Double.valueOf(sum / values.size());
};
static final Function<Collection<Integer>, Double> medianer = (values) -> {
List<Integer> sorted = new ArrayList<>(values);
sorted.sort(Comparator.comparingDouble(Number::doubleValue));
// TODO treat odd/even number of elements separately
return Double.valueOf(sorted.get(sorted.size() / 2).doubleValue());
};
Followed later by:
Collection<Function<Collection<Integer>, Double>> functions = new ArrayList<>();
functions.add(averager);
functions.add(medianer);
For the case of callable you can nicely inline them:
Collection<Callable<Double>> callables = new ArrayList<>();
callables.add(() -> {
double sum = 0.0;
for (Integer value : values) {
sum += value.doubleValue();
}
return Double.valueOf(sum / values.size());
});
callables.add(() -> {
List<Integer> sorted = new ArrayList<>(values);
sorted.sort(Comparator.comparingDouble(Number::doubleValue));
// TODO treat odd/even number of elements separately
return Double.valueOf(sorted.get(sorted.size() / 2).doubleValue());
});
Note how you do not need external declarations in the latter case.
Note: as you do not want your results in a random order you will need you function return a pair, e.g. Map.Entry, with a key and a value. But I will leave that to you to exercise.
A sample execution for one of those methods would print something like
[53.01,57.0]

You can pass as a constructor argument. Also, after starting the threads, you must call join, otherwise the main thread will not wait the others to finish:
average.start();
median.start();
deviation.start();
average.join();
median.join();
deviation.join();
```

Related

Generic Supplier for n Getters Across Collection

I have a collection of Java objects where I want to run a single function across multiple values I might find in some of the object's member variables. I'm looking for a nice way to pass in which getter should be used so I can have one method do all that work. I was thinking about something like a Supplier, but that would mean I have to have one per instance of the class. Here's an example of what I'm trying to do (only I would like to do this without the if statement or with potentially n getters a switch statement:
import java.util.ArrayList;
import java.util.List;
public class TestSupplier {
private int varA;
private int varB;
public TestSupplier(int varA, int varB) {
this.varA = varA;
this.varB = varB;
}
public int getA() {
return this.varA;
}
public int getB() {
return this.varB;
}
public static void main(String[] args) {
List<TestSupplier> testList = new ArrayList<>();
testList.add(new TestSupplier(1, 11));
testList.add(new TestSupplier(2, 22));
// Can I pass something like a generic supplier instead of a bool?
TestSupplier.someCollectorFunction(testList, true);
TestSupplier.someCollectorFunction(testList, false);
}
public static void someCollectorFunction(List<TestSupplier> list, boolean isA /* what if I want more than one getter*/) {
int sum = 0;
for (TestSupplier obj: list) {
// This is where I wish I could have a generic supplier or something
if (isA) {
sum = sum + obj.getA();
}
else {
sum = sum + obj.getB();
}
}
System.out.println("I have a sum: " + sum);
}
}
Is there something is Java's functional API that would let me do this?
It sounds like what you want is
ToIntFunction<TestSupplier> fn = isA ? TestSupplier::getA : TestSupplier::getB;
for (TestSupplier obj: list) {
sum += fn.applyAsInt(obj);
}
It's up to you whether you consider that an improvement.
You could also pass in the ToIntFunction instead of the boolean, passing in TestSupplier::getA instead of true etc.

Affect some logic lists using java stream [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I am trying to change the loop to Java streams.
For example,
interface Logic {
int apply(int value);
}
public class AddOneLogic implements Logic {
#Override
public int apply(int value) {
return value + 1;
}
}
public class AddTwoLogic implements Logic {
#Override
public int apply(int value) {
return value + 2;
}
}
Using a loop to apply a Logic looks like
List<Logic> logics = new ArrayList<>();
logics.add(new AddOneLogic());
logics.add(new AddTwoLogic());
int init = 1;
I want to change to streams below. Is there any better way to do it?
int result = init;
for (Logic logic : logics) {
result = logic.apply(result);
}
As #duffymo mentioned in the comments, these classes aren't particularly useful and they could be replaced with Function<Integer, Integer>s and lambda expressions to define them.
In that case, you may want to reduce a list/stream of Functions by Function::andThen,
Function<Integer, Integer> addOneFunction = i -> i + 1;
Function<Integer, Integer> addTwoFunction = i -> i + 2;
Function<Integer, Integer> function =
Stream.of(addOneFunction, addTwoFunction)
.reduce(Function.identity(), Function::andThen);
so you would get a composed function to work with
Integer result = function.apply(init);
// ((1 + 1) + 2) = 4
You can do it with Stream and AtomicInteger and getAndSet(int) method as below,
AtomicInteger result = new AtomicInteger(1);
logics.stream().forEach(ele-> result.getAndSet(ele.apply(result.get())));
// result = ((1+1)+2)=4
Better option would be to use Function,
Function<Integer, Integer> addOne = i -> i + 1;
Function<Integer, Integer> addTwo = i -> i + 2;
List<Function<Integer, Integer>> logics = new ArrayList<>();
logics.add(addOne);
logics.add(addTwo);
AtomicInteger result = new AtomicInteger(1);
logics.stream().forEach(ele-> result.getAndSet(ele.apply(result.get())));
You can even avoid logics list and use andThen method as below,
Function<Integer, Integer> add = addOne.andThen(addTwo);
result = add.apply(1);
Hope it helps..!!
As others have already mentioned: The intention behind the question might be distorted by the attempt to simplify the question so that it can be posted here. The Logic interface does not really make sense, because it could be replaced with an IntUnaryOperator.
Not with a Function<Integer, Integer> - that's a different thing!
But I'll (also) make some assumptions when trying to answer the question:
The Logic interface is merely a placeholder for an interface that has to be retained in its current form
Several Logic instances can sensibly be combined in order to yield an new Logic
The goal is not to "apply streams for the streams sake", but to create sensible, usable classes and methods (and it's a pity that this is worth mentioning...)
If this is the case, then I'd suggest creating a CombinedLogic class that simply offers a method for combining several Logic objects to create the combined one.
It could also be a concrete class that internally stores a List<Logic>. This might be handy in order to modify a combined logic later, as in combinedLogic.setElement(42, new OtherLogic());. But a public class with a modifiable state should be thought through carefully...
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class CombinedLogicExample {
public static void main(String[] args) {
List<Logic> logics = new ArrayList<>();
logics.add(new AddOneLogic());
logics.add(new AddTwoLogic());
Logic combined = CombinedLogic.of(logics);
// Alternatively:
// Logic logic1 = new AddOneLogic();
// Logic logic2 = new AddTwoLogic();
// Logic combined = CombinedLogic.of(logic1, logic2);
int init = 1;
int result = combined.apply(init);
System.out.println(result);
}
}
class CombinedLogic {
static Logic of(Logic... logics) {
return of(Arrays.asList(logics));
}
static Logic of(Iterable<? extends Logic> logics) {
return a -> {
int result = a;
for (Logic logic : logics) {
result = logic.apply(result);
}
return result;
};
}
}
interface Logic {
int apply(int value);
}
class AddOneLogic implements Logic {
#Override
public int apply(int value) {
return value + 1;
}
}
class AddTwoLogic implements Logic {
#Override
public int apply(int value) {
return value + 2;
}
}

ConcurrentModificationException when trying to sum numbers of an Arraylist using multiple threads in Java

I'm new to multithreading in general, so I still don't fully understand it. I don't get why my code is having issues. I'm trying to populate an ArrayList with the first 1000 numbers, and then sum all of them using three threads.
public class Tst extends Thread {
private static int sum = 0;
private final int MOD = 3;
private final int compare;
private static final int LIMIT = 1000;
private static ArrayList<Integer> list = new ArrayList<Integer>();
public Tst(int compare){
this.compare=compare;
}
public synchronized void populate() throws InterruptedException{
for(int i=0; i<=Tst.LIMIT; i++){
if (i%this.MOD == this.compare){
list.add(i);
}
}
}
public synchronized void sum() throws InterruptedException{
for (Integer ger : list){
if (ger%MOD == this.compare){
sum+=ger;
}
}
}
#Override
public void run(){
try {
populate();
sum();
System.out.println(sum);
} catch (InterruptedException ex) {
Logger.getLogger(Tst.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) {
Tst tst1 = new Tst(0);
tst1.start();
Tst tst2 = new Tst(1);
tst2.start();
Tst tst3 = new Tst(2);
tst3.start();
}
}
I expected it to print "500.500‬", but instead it prints this:
162241
328741
Exception in thread "Thread-0" java.util.ConcurrentModificationException
at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1042)
at java.base/java.util.ArrayList$Itr.next(ArrayList.java:996)
at tst.Tst.sum(Tst.java:38)
at tst.Tst.run(Tst.java:50)
BUILD SUCCESSFUL (total time: 2 seconds)
The problem is happening because your methods are synchronized in "object level", I mean, the monitor lock it uses is of a particular object (tst1,tst2,tst3). In other words, each synchronized method is using a different lock.
Change your synchronized methods to static as a first step to fix it.
while run of tst1 is counting the sum in for-each then run of tst2 might increasing the size of list. So its throwing concurrent modification exception. Using a join can help.
public static void main(String[] args) {
Tst tst1 = new Tst(0);
tst1.start();
tst1.join()
Tst tst2 = new Tst(1);
tst2.start();
tst1.join()
Tst tst3 = new Tst(2);
tst3.start();
}
You misunderstood the semantic of synchronized method, each one uses different lock object in your case, do it this way:
class SynchList {
private int sum = 0;
private final int MOD = 3;
private int compare;
private final int LIMIT = 1000;
private ArrayList<Integer> list = new ArrayList<Integer>();
public synchronized void populate( int compare) throws InterruptedException{
for(int i=0; i<=LIMIT; i++){
if (i%this.MOD == compare){
list.add(i);
}
}
}
public synchronized void sum( int compare ) throws InterruptedException{
for (Integer ger : list){
if (ger%MOD == compare){
sum+=ger;
}
System.out.println( sum );
}
}
}
class Tst extends Thread {
int compare;
SynchList synchList;
public Tst(int compare, SynchList synchList)
{
this.compare= compare;
this.synchList = synchList;
}
#Override
public void run(){
try {
synchList.populate( compare );
synchList.sum( compare );
} catch (InterruptedException ex) {
Logger.getLogger(Tst.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public class Main
{
public static void main(String[] args) {
SynchList synchList = new SynchList();
Tst tst1 = new Tst( 0 , synchList );
tst1.start();
Tst tst2 = new Tst( 1, synchList );
tst2.start();
Tst tst3 = new Tst( 2, synchList );
tst3.start();
}
}
Your use of synchronized methods isn't doing what you think it's doing. The way your code is written, the methods "sum" and "populate" are protected
from running at the same time, but only on the same thread instance. That means calls to "sum" and "populate" for a single Tst object will happen one at a time,
but simultaneous calls to "sum" on different object instances will be allowed to happen concurrently.
Using synchronized on a method is equivalent to writing a method that is wrapped
with synchronized(this) { ... } around the entire method body. With three different instances created – tst1, tst2, and tst3 – this form of synchronization
doesn't guard across object instances. Instead, it guarantees that only one of populate or sum will be running at a time on a single object; any other calls to one of
those methods (on the same object instance) will wait until the prior one finishes.
Take a look at 8.4.3.6. synchronized Methods in the Java Language Specification
for more detail.
Your use of static might also not be doing what you think it's doing. Your code also shares things across all instances of the Tst thread class – namely, sum and list. Because these are defined as static,
there will be a one sum and one list. There is no thread safety in your code to guard against concurrent changes to either of those.
For example, as threads are updating
"sum" (with the line: sum+=ger), the results will be non-deterministic. That is, you will likely see different results every time you run it.
Another example of unexpected behavior with multiple threads and a single static variable is list – that will grow over time which can result in concurrency issues. The Javadoc says:
Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally.
Modifications include adding values as well as growing the backing array store. Without specifying a starting size – new ArrayList() – it will default to 10 or possibly some other relatively small number depending on which JVM version you're using. Once one thread tries to add an item that exceeds the ArrayList's capacity, it will trigger an automatic resize.
Each ArrayList instance has a capacity. The capacity is the size of the array used to store the elements in the list. It is always at least as large as the list size. As elements are added to an ArrayList, its capacity grows automatically. The details of the growth policy are not specified beyond the fact that adding an element has constant amortized time cost.

Passing the method to method

I have a method which uses Deque. In 1 place, sometimes I want to Deque.pullFirst() and sometimes Deque.pullLast(). It should depend on one of the arguments passed to the method. How do this with Java 8?
This is my try with Callable I know that it doesn't work but now you can understand what I want to achieve:
public class AppMain {
public void iterateThroughQueue(Callable callable) { // error
Deque<Integer> deq = new ArrayDeque<>();
deq.add(1);
deq.add(2);
deq.add(3);
for (int i = 0; i < 3; i++) {
System.out.println(callable.apply(deq)); // error!
}
System.out.println("size after iteration = " + deq.size());
}
public static void main(String[] args) {
AppMain.iterateThroughQueue(Deque::pollFirst); // error!
}
}
Method references are either:
Consumer<T>, which means they take a parameter and return nothing. For example System.out::println is a Consumer<String>.
Producer<T>, which means they take no parameter and return something. For example UUID::randomUUID is a Producer<UUID>.
Function<T,Z>, which means they take a parameter of type T (can be the instance on which to apply the method) and return a result of type Z, in your case Deque::pollFirst take is a Function<Deque<Integer>, Integer>. Another example is deq::add where deq is an instance of Deque<Integer> which would be a Function<Integer, Boolean> .
So you should be using Function<Deque<Integer>, Integer> instead of Callable which is for something completely different. Also iterateThroughQueue(...) need to be static.
Callable will not work here, but Function will.
You could try instead this:
public static void iterateThroughQueue(Function<Deque<Integer>, Integer> function) {
Deque<Integer> deq = new ArrayDeque<>();
deq.add(1);
deq.add(2);
deq.add(3);
for (int i = 0; i < 3; i++) {
System.out.println(function.apply(deq));
}
System.out.println("size after iteration = " + deq.size());
}
public static void main(String[] args) {
iterateThroughQueue(Deque::pollFirst);
}
This prints:
1
2
3
size after iteration = 0

Java math DescriptiveStatistics remove value

I am new to Java and have been using it with Esper CEP engine. This question is however unrelated to Esper, its more of a Java question.
First, my class :-
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.commons.math3.stat.descriptive.DescriptiveStatistics;
import com.espertech.esper.epl.agg.AggregationSupport;
import com.espertech.esper.epl.agg.AggregationValidationContext;
public class CustomPercentiles extends AggregationSupport {
private List<Double> numbers = new ArrayList<Double>();
public CustomPercentiles(){
super();
}
public void clear() {
numbers.clear();
}
public void enter(Object arg0) {
Double value = (Double) (double) (Integer) arg0;
if (value > 0){
//Not interested in < 1
numbers.add(value);
}
}
public void leave(Object arg0) {
Double value = (Double) (double) (Integer) arg0;
if (value > 0){
//Not interested in < 1
numbers.remove(value);
}
}
public Object getValue() {
DescriptiveStatistics stats = new DescriptiveStatistics();
Map<String, Integer> result = new HashMap<String, Integer>();
for (Double number:numbers.subList(0, numbers.size())){
stats.addValue(number);
}
result.put("median", (int) stats.getPercentile(50));
result.put("pct90", (int) stats.getPercentile(90));
result.put("pct10", (int) stats.getPercentile(10));
result.put("mean", (int) stats.getMean());
result.put("std", (int) stats.getStandardDeviation());
return result ;
}
public Class getValueType() {
return Object.class;
}
#Override
public void validate(AggregationValidationContext arg0) {
// TODO Auto-generated method stub
}
}
Basically, Esper will call enter(value) and leave(value) whenever it wants based on logic irrelevant here. And it calls getValue() to get the results computed.
Since I want to calculate percentiles, I need all the numbers available to process this. To do this, I store it in a global list called numbers, and in getValue() I put all the numbers into a DescriptiveStatistics instance and then process the stats I need.
My presumption is that each time i put the list as a new DescriptiveStatistics object, it needs to do sorting. Is there some way i can maintain a DescriptiveStatistics-like object as my global object?
The only reason i use ArrayList vs DescriptiveStatistics as my global object is that DescriptiveStatistics does not have a remove method. I.e. i cannot remove an object by value.
In practice, there are hundreds of instances of this class running at any given time, and getValue() for each of them is called every 1 to 10 second. I don't have any performance issues at the moment, but am looking for some optimization help to avoid future problems.
Alternate explanation :-
What i am doing here is mantaining a list of numbers. Esper will call the enter() and leave() methods many times to tell me what numbers should remain in the list. This in my case is a time based aggregation. Ive told esper that I want to compute based on numbers from last 1 minute.
So on 00:00:00 esper calls enter(10)
my numbers becomes [10]
So on 00:00:05 esper calls enter(15)
my numbers becomes [10, 15]
So on 00:00:55 esper calls enter(10)
my numbers becomes [10, 15, 10]
So on 00:01:00 esper calls leave(10)
my numbers becomes [15, 10]
So on 00:01:05 esper calls leave(15)
my numbers becomes [15]
Now in this duration getValue() may have been called numerous times. Each time it is called, it is expected to return calculations based off the current contents of numbers.
getValue() calculates the 10th, 50th and 90th percentiles. In order to calculate percentiles, DescriptiveStatistics needs to sort the numbers. (10th percentile of 100 numbers would be the 10th number of the list after sorting it.).
So im looking for a way to be able to take out any arbitary number from DescriptiveStatistics instance. Or asking for recommendation for some other library that can give me medians and percentiles while having the ability to take out a number from the list while knowing the value.
DescriptiveStatistics has a removeMostRecentValue(), but thats not what I want to do.
To my understanding, you're asking for a way to use the DescriptiveStatistics-class as the list, instead of "numbers". Meaning, you want to dynamically add and remove numbers from the DescriptiveStatistics-variable.
As far as I can see, there's no better way to do this than what you're doing now.
Are you sure that you need the feature to remove a specific number from the list, before calculating the percentile again? Wouldn't it always be new numbers?
It sounds a bit like you would want to learn some more basics of Java.
Anyway, since I can't really give you a qualified answer to your question, I figured I would at least help you with correcting some of your code, to follow better practices:
public class CustomPercentiles extends AggregationSupport {
private List<Double> numbers = new ArrayList<Double>();
//Methods that are inherited from super-classes and interfaces
//should have the "#Override" annotation,
//both for the compiler to check if it really is inherited,
//but also to make it more clear which methods are new in this class.
#Override
public void clear() {
numbers.clear();
}
#Override
public void enter(Object value) {
double v = (double) value;
if (v > 0){
numbers.add(v);
}
}
#Override
public void leave(Object value) {
double v = (double) value;
if (v > 0){
numbers.remove(v);
}
}
#Override
public Object getValues() {
DescriptiveStatistics stats = new DescriptiveStatistics();
Map<String, Integer> result = new HashMap<String, Integer>();
//It is unnecessary to call number.subList(0, numbers.size())
//since it will just return the entire list.
for (Double number : numbers){
stats.addValue(number);
}
result.put("median", (int) stats.getPercentile(50));
result.put("pct90", (int) stats.getPercentile(90));
result.put("pct10", (int) stats.getPercentile(10));
result.put("mean", (int) stats.getMean());
result.put("std", (int) stats.getStandardDeviation());
return result ;
}
//Judgning from the API of AggregationSupport,
//I would say this method should return Double.class
//(it basically seems like a bad way of implementing generics).
//Are you sure it should return Object.class?
public Class getValueType() {
return Object.class;
}
#Override
public void validate(AggregationValidationContext arg0) {
// TODO Auto-generated method stub
}
}

Categories