I have a set of objects. This objects calculate some numbers based on request parameters. Let's call them calculators. Each calculator has description where specified type of requests that this calculator the most suitable for. For example,
Calculator1 : with this parameters : price > 10, gender = male, geo_id = 1, 2 or 3.
Calculator2 : with this parameters : price < 5, gender = male, geo_id = 1, 2.
For request : price = 11, gender = male, geo_id = 2
I should get calculator1 like the most suitable and then calculator2.
For request : price = 4, gender = male, geo_id = 2
I should get calculator2 and then calculator1.
For request : price = 3, gender = female, geo_id = 5
I should get only the second one.
Now I'm doing it with Lucene, but it's not really fit for this task. Can you recommend me some library or approach?
My suggestion would be to use a comparator. See a sketch of the classes below.
import java.util.HashMap;
import java.util.Map;
public abstract class Calculator {
public static Map<String, Integer> weights;
static {
weights = new HashMap<String, Integer>();
weights.put("price", 10);
weights.put("gender", 2);
weights.put("geo", 5);
}
public abstract int calculate(Map<String, Integer> request);
public abstract int fitnessFor(Map<String, Integer> request);
}
You can use the weights to adjust relative importance of the individual request parameters.
import java.util.Map;
public class Calculator1 extends Calculator {
public int calculate(Map<String, Integer> request) {
return -1;
}
@Override
public int fitnessFor(Map<String, Integer> request) {
int fitness = -1;
Integer price = request.get("price");
if (price == null)
return fitness;
if (price > 10)
fitness += weights.get("price");
return fitness;
}
public String toString() { return "Calculator1"; }
}
Calculator1 cares only about the pricey items.
import java.util.Map;
public class Calculator2 extends Calculator {
public int calculate(Map<String, Integer> request) {
return -1;
}
@Override
public int fitnessFor(Map<String, Integer> request) {
int fitness = -1;
Integer price = request.get("price");
if (price == null)
return fitness;
if (price < 5)
fitness += weights.get("price");
Integer gender = request.get("gender");
if (gender == null)
return fitness;
if (gender == 1)
fitness += weights.get("gender");
return fitness;
}
public String toString() { return "Calculator2"; }
}
Calculator2 cares about the less pricey items esp. if they are for gender 1.
The comparator just compares Calculators by their fitness relative to the request:
import java.util.Comparator;
import java.util.Map;
public class CalcComparator implements Comparator<Calculator> {
private Map<String, Integer> request;
public CalcComparator(Map<String, Integer> request) {
this.request = request;
}
@Override
public int compare(Calculator c1, Calculator c2) {
int c1Fitness = c1.fitnessFor(request);
int c2Fitness = c2.fitnessFor(request);
if (c1Fitness == c2Fitness)
return 0;
if (c1Fitness < c2Fitness)
return 1;
return -1;
}
}
Try it out with:
public class Main {
public static void main(String[] args) {
Map<String, Integer> request = new HashMap<String, Integer>();
request.put("price", 5);
request.put("gender", 1);
List<Calculator> calculators = new ArrayList<Calculator>();
calculators.add(new Calculator1());
calculators.add(new Calculator2());
Collections.sort(calculators, new CalcComparator(request));
System.out.println("For request: "+request);
for (Calculator c : calculators) {
System.out.println("\t"+c.toString() + "( fitness " + c.fitnessFor(request) + ")");
}
}
}
This is just a sketch to illustrate the idea. You will probably want to introduce an enum for the request parameters, maybe introduce a Request class, most likely change completely how fitness is computed, make some of the fields private and encapsulate them, etc.
The advantage is that you easily get an ordering of all the Calculators based on their fitness for the request.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments