I am writing a Java class to parse a file with something like the following:
[thread 16] INFO - L3: createOrder: min [239.0] max [1245.0] average [488.06]
[thread 16] INFO - L3: translateBarCode: min [9.0] max [132.0] average [31.1]
[thread 11] INFO - L3: createOrder: min [258.0] max [2458.0] average [506.31]
[thread 13] INFO - L3: createOrder: min [243.0] max [1303.0] average [542.57]
[thread 11] INFO - L3: translateBarCode: min [9.0] max [104.0] average [29.79]
[thread 13] INFO - L3: translateBarCode: min [9.0] max [129.0] average [37.94]
[thread 5] INFO - L3: createOrder: min [269.0] max [1269.0] average [479.95]
[thread 5] INFO - L3: translateBarCode: min [9.0] max [124.0] average [30.34]
[thread 3] INFO - L3: createOrder: min [236.0] max [1238.0] average [492.35]
[thread 3] INFO - L3: translateBarCode: min [10.0] max [108.0] average [32.04]
[thread 16] INFO - L3: changeOrder: min [662.0] max [4204.0] average [1379.84]
[thread 17] INFO - L3: createOrder: min [236.0] max [1335.0] average [521.18]
[thread 16] INFO - L3: translateBarCode: min [10.0] max [112.0] average [34.87]
[thread 17] INFO - L3: translateBarCode: min [10.0] max [103.0] average [36.45]
[thread 13] INFO - L3: changeOrder: min [617.0] max [4094.0] average [1520.84]
[thread 13] INFO - L3: translateBarCode: min [9.0] max [108.0] average [31.38]
[thread 11] INFO - L3: changeOrder: min [620.0] max [4099.0] average [1316.38]
[thread 5] INFO - L3: changeOrder: min [647.0] max [4154.0] average [1384.15]
[thread 5] INFO - L3: translateBarCode: min [8.0] max [110.0] average [31.42]
...
...
I am able to successfully get it into a CVS format of something like this using basic substr and Collections.sort type stuff:
API, Min, Max, Average
capturePayment, 232.0, 1800.0, 687.68
capturePayment, 268.0, 1853.0, 761.44
capturePayment, 301.0, 2612.0, 753.69
capturePayment, 309.0, 2632.0, 766.31
...
...
My problem is that I want to average out all of the duplicate API times into one entry per API (ie an average min/max/average for each API). There are duplicates in the original file and it’s not sorted so I am not sure how to proceed.
My biggest problem is that the number of APIs won’t always be the same, ie there might be 10 capturePayment calls but 20 createOrders. Otherwise I have a roughly working model. Could someone please give me some pointers?
[Edit]
With the “registerAPI” solution below, I am almost there. The averages being calculated are slightly off from what they should be based in Excel. Here is my code. My only thoughts are possibly casting from Strings to Doubles messes up the precision?
while ((line = br.readLine()) != null) {
if (line.contains("L3")) {
int x,y;
x = line.indexOf("L3: ") + "L3: ".length();
y = line.indexOf(":", x);
String name = line.substring(x,y).trim();
x = line.indexOf("min [") + "min [".length();
y = line.indexOf("]", x);
String min = line.substring(x,y).trim();
x = line.indexOf("max [") + "max [".length();
y = line.indexOf("]", x);
String max = line.substring(x,y).trim();
x = line.indexOf("average [") + "average [".length();
y = line.indexOf("]", x);
String average = line.substring(x,y).trim();
pStreamArray.add(name + ", " + min + ", " + max + ", " + average);
double[] apiValues = new double[3];
apiValues[0] = Double.valueOf(min);
apiValues[1] = Double.valueOf(max);
apiValues[2] = Double.valueOf(average);
parseAPILogs.registerAPI(name, apiValues);
}
}
Iterator iterator = averagePerAPI.keySet().iterator();
while (iterator.hasNext()) {
String key = iterator.next().toString();
double[] values = averagePerAPI.get(key);
String valueString = "";
for (int i = 0; i < values.length; i++) {
valueString += values[i] + ", ";
}
System.out.println(key + " " + valueString);
pStreamCombined.println(key + " " + valueString);
}
[Edit]
I have found the mathematical flaw in the code above – The average of 3 numbers does not equal the average of the first two and then the averaging into it the third.
Example:
(395+415+412)/3=407.33
(395+415)/2=405
(405+412)/2=408.5
As I see it, you can achieve this with a
Mapand an average container.The container is a class that has the current sum of
MIN,MAXandAVERAGEalongside with the current count:On with the map:
The key of this map is an API’s name and the value is an array of
doublewith a size of 3 where you save{MIN, MAX, AVERAGE}in that particular order due to the logic of the code above.Finally, you just manage the map by making use of the different methods it provides. Take, for example, a method
registerAPIthat saves an API’s data updates an existing one.When you want to know a particular value for an API, you just invoke
getAPIMin(),getAPIMax()orgetAPIAverage()methods.