Need to do aggregation of Cartesian product of two hierarchical tree structures using Java, Please suggest some good methods or API to do this.
Tree Structure:
Country Tree :
Node|Id|ParentId
World|1|1
Asia|2|1
Europe|3|1
India|4|2
China|5|2
UK|6|3
Hungary|7|3
Cyprus|8|3
Profit Tree:
Node|Id|ParentId
Profit|1|1
Revenue|2|1
Expense|3|1
Cartesian product of these two products would give me 24 combinations (8 X 3). I need to aggregate values for each of the combination.
For example, I want to know Total revenue of Europe, Asia and World, Total Profit of Europe etc
It's a bit hard to answer without details of the structures. But I'll guess what they might be and you can extrapolate to your structures.
enum EconomicDataType {
PROFIT, REVENUE, EXPENSE;
}
interface GeographicNode {
int getEconomicData(EconomicDataType type);
}
class Region implements GeographicNode {
private List<GeographicNode> geographiesInRegion;
public int getEconomicData(EconomicDataType type) {
return geographiesInRegion.stream()
.mapToInt(geog -> geog.getEconomicData(type))
.sum();
}
}
class Country implements GeographicNode {
private EnumMap<GeographicNode, Integer> economicData;
public int getEconomicData(EconomicDataType type) {
return economicData.get(type);
}
}
I have modelled economic data as a map rather than a tree because, frankly, it makes no sense to me to make it a hierarchy given there's nothing hierarchical about the data.
I also haven't handled the situation in which data is missing. Not hard to add with a containsKey check before getting the data from the map.
Retrieving someing like total revenue for europe is:
europe.getEconomicData(EconomicDataType.REVENUE);
Simple :-)
Related
I have the following dataset, and am trying to work out how to best write a specific constraint.
My PlanningEntity looks (roughly) as follows:
#PlanningEntity
public class Participation {
#PlanningId
private long id;
private Student student;
private Lesson lesson;
#PlanningVariable(valueRangeProviderRefs = "possibleEnrollments")
private Boolean enrolled;
}
whereby a Lesson has a public List<Subject> getSubjects() (note: a list of multiple subjects).
What I would like to do in my penalize method is look at all participations of a student/subject (single subject!) combination. In other words, if I have lesson A with subject 1, lesson B with subject 2 and lesson C with subjects 1 and 2, I would like to do a grouping in such a way that in my penalize function I get two (Student, List<Participation>) callbacks: one for subject 1 and one for subject 2, whereby the first lists contains lessons A and C, and the second list has lessons B and C. So, C is contained in two lists.
The following does not work:
constraintFactory
.forEach(Participation.class)
.groupBy(Participation::getStudent, Participation::getSubjects, toList())
since this groups on the entire List returned by Participation::getSubject and the set 1 and 2 attached to lesson C becomes a separate group.
I have currently 'solved' the problem as follows, with a custom UniConstraintCollection:
return constraintFactory
.forEach(Participation.class)
.groupBy(Participation::getStudent, new UniConstraintCollector<Participation, Map<Subject, List<Participation>>, Map<Subject, List<Participation>>>() {
#Override
public Supplier<Map<Subject, List<Participation>>> supplier() {
return HashMap::new;
}
#Override
public BiFunction<Map<Subject, List<Participation>>, Participation, Runnable> accumulator() {
return (map, participation) -> {
for(Subject s : participation.getSubjects()) {
if(!map.containsKey(s)) {
map.put(s, new ArrayList<>());
}
map.get(s).add(participation);
}
return () -> {
for(Map.Entry<Subject, List<Participation>> entry: map.entrySet()) {
entry.getValue().remove(participation);
}
};
};
}
#Override
public Function<Map<Subject, List<Participation>>, Map<Subject, List<Participation>>> finisher() {
return Function.identity();
}
}).penalize(("name", HardSoftScore.ONE_SOFT, (student, participationMap) -> {
...
});)
This works, in that I receive a map of Subject to Participations and allows me to calculate the penalty I want.
However, this means that I calculate one penalty value for all subject/list combinations 'together'. From a usability perspective, I would like to penalize each subject/list separately. Is there a way to do this? (Maybe by rewriting the UniConstraintCollector to provide multiple lists of Participations, instead of one single Map<Subject, List<Participation>>?)
P.S. Another approach I have tried to achieve the same goal is to work from the perspective of the Subject. So, making Subjects a ProblemFact on the PlanningSolution, and working with something like
return constraintFactory
.forEach(Subject.class)
.join(constraintFactory.forEach(Participation.class),
JoinerSupport.getJoinerService().newBiJoiner(List::of, JoinerType.INTERSECTING, Participation::getSubjects)
)
I assume this is the way I would need to go, using the JoinerType INTERSECTING, but this gives me an "Unsupported Joiner Type" exception in AbstractLeftHandSide.
What if you start from Subject?
constraintFactory
.forEach(Subject.class)
.join(Participation.class,
// Joiners.containedBy() would do this far more efficient
filtering((s, p) -> p.getSubjects().contains(s))
.groupBy((s, p) -> s, toList((s, p) -> p))
This could be an expensive constraint performance wise. Benchmark it.
This isn't really an answer, but it might solve your problem too. It's too long to add as a comment.
The Boolean planning variable is typically an anti-pattern.
If you improve your model, the constraint might become easier to implement.
Instead, you could model it like this:
#PlanningEntity
public class Participation {
#PlanningId long id;
Student student;
#PlanningVariable(...) Lesson lesson;
}
This simpler model (on the right) will solve far more efficiently. But in this case, how many Participation instances should you create?
If the numbers of lessons for each student is fixed, that's obvious: that number per student.
If the numbers of lessons for each student is a planning decision, use overconstrainted planning: #PlanningVariable(nullable=true,...) Lesson lesson and create one participation for the maximum number of lessons of each student. This will allow the solver to leave some participation instances unassigned.
See also the Domain Modeling Guide in the docs.
I'm learning Java for the first time (my prior experience is Python and Haskell). I have a situation that would, in Python, require a "decorate and sort" idiom. Such as the following (code not tested but this is roughly correct):
origList = <something>
decorated = sorted( [(evalFunc(item), item) for item in origList] )
finalList = [item for _, item in decorated]
By choosing a different evalFunc you can choose how this is sorted.
In Java, I'm writing a program that composes music by choosing from among a list of notes, evaluating the "fitness" of each note, and picking the best. I have a class representing musical notes:
class Note {
...
}
I have a class that represents the fitness of a note as two values, its goodness and badness (yes, these are separate concepts in my program). Note: in Python or Haskell, this would simply be a 2-tuple, but my understanding is that Java doesn't have tuples in the usual sense. I could make it a pair, but it gets unwieldy to declare variables all over the place like List<Pair<Type1,Pair<Type2,Type3>>>. (As an aside, I don't think Java has type aliases either, which would let me shorten the declarations.)
class Fitness {
double goodness;
double badness;
}
The function that evaluates the fitness needs access to several pieces of data other than the Note. We'll say it's part of a "Composition" class:
class Composition {
... data declared here ... ;
public Fitness evaluate(Note n) {
}
}
I'd like to be able to compare Fitness objects in numerical order. There are two ways to compare: either goodness or badness can be numerically compared, depending on the situation.
class CompareFitnessByGoodness implements Comparator<Fitness> {
}
class CompareFitnessByBadness implements Comparator<Fitness> {
}
I'd like to package the Note together with its fitness, so I can sort the combined list by fitness and later pull out the best Note.
class Together {
public Note;
public Fitness;
}
I'd like to sort a List<Together> by either the goodness, or by the badness. So I might need:
class CompareTogetherByGoodness implements Comparator<Together> {
...
}
class CompareTogetherByBadness implements Comparator<Together> {
...
}
Eventually I'll write something like
Note pickBest(List<Together> notes) {
// Pick a note that's not too bad, and pretty good at the same
// time.
// First sort in order of increasing badness, so I can choose
// the bottom half for the next stage (i.e. the half "least bad"
// notes).
Collections.sort(notes, new CompareTogetherByBadness());
List<Together> leastBadHalf = notes.subList(0, notes.size()/2);
// Now sort `leastBadHalf` and take the last note: the one with
// highest goodness.
Collections.sort(leastBadHalf, new CompareTogetherByGoodness());
return leastBadHalf.get(leastBadHalf.size()-1);
}
Whew! That is a LOT of code for something that would be a few lines in Haskell or Python. Is there a better way to do this?
EDIT:
Addressing some of the answers.
"You don't need to decorate." Well, my fitness computation is very expensive, so I want to compute it once for each note, and save the result for later access as well.
"Store goodness/badness in Note." The goodness or badness is not a property of the note alone; it's only meaningful in context and it can change. So this is a suggestion that I add mutable state which is only meaningful in some contexts, or plain wrong if there's a bug which accidentally mutates it. That's ugly, but maybe a necessary crutch for Java.
Going by what you already have
origList = <something>
decorated = sorted( [(evalFunc(item), item) for item in origList] )
finalList = [item for _, item in decorated]
This is the equivalent in modern Java:
Given your composition object:
Composition composer = ...;
And a list of notes:
List<Note> notes = ...;
Then you can do:
List<Together> notesAllTogetherNow = notes.stream()
.map(note -> new Together(note, composer.evaluate(note)))
.sorted(new CompareTogetherByGoodness())
.collect(Collectors.toList());
To get the best note, you can take a bit further:
Optional<Note> bestNote = notes.stream()
.map(note -> new Together(note, composer.evaluate(note)))
.sorted(new CompareTogetherByBadness())
.limit(notes.size() / 2) // Taking the top half
.sorted(new CompareTogetherByGoodness())
.findFirst() // Assuming the last comparator sorts in descending order
.map(Together::getNote);
You can use streams:
Function<Foo, Bar> func = ...
Comparator<Foo> comparator = ...
var list = ...
var sorted = list.stream()
.sorted(comparator)
.map(func)
.collect(Collectors.toList());
Java plainly includes a Collections.sort :: List -> Comparator -> List that does everything for you. It mutates the original list, though.
Unfortunately, Java's standard library does not include tuples and even a plain Pair; the Apache Commnons library does, though.
In short, you don't need the decorate / undecorate approach in Java.
class Fitness {
double goodness;
double badness;
}
class Together {
Note note;
Fitness fitness;
}
class Note{
}
List<Together> notes = ...
Collections.sort(notes, Comparator.comparingDouble(value -> value.fitness.badness));
List<Together> leastBadHalf = notes.subList(0, notes.size()/2);
return leastBadHalf.stream().max(Comparator.comparingDouble(value -> value.fitness.goodness));
For example:
class Vehicle {
Collection<Axle> axles;
}
class Axle {
Collection<Wheel> wheels;
}
class Wheel {
// I think there are dually rims that take two tires -- just go with it
Collection<Tire> tires;
}
class Tire {
int width;
int diameter;
}
I have a service through which I can get a collection of all Vehicle objects I know about. Now say I have a tire of a specific width and diameter, and I want to find a Vehicle which can take it. The simplistic way is to have a set of four nested loops, like so:
for (Vehicle vehicle : vehicles) {
for (Axle axle : vehicle.getAxles()) {
for (Wheel wheel : axle.getWheels()) {
for (Tire tire : wheel.getTires()) {
if (tire.width == targetWidth
&& tire.diameter == targetDiameter) {
// do something
break;
}
}
}
}
}
Is there a good design pattern for this? Or a better data structure to use? Would it be better to just keep an index somewhere of tire information mapped to vehicles?
edit: answering questions from comments
Do you have control over the structure of the data you receive from the service?
Yes
Do you need to search for different tires multiple times in the same data?
Yes
Is performance an issue?
Not especially
When you find the tire, do you just need to know which vehicle contains it or do you also need the axle and wheel?
Sometimes just the vehicle, sometimes just the axle -- two different contexts
Do you need the reference to the tire that was found?
Yes, in the cases where I need the axle
edit2:
Extending the metaphor further, to explain the two contexts above:
Context 1 -- I want to know the vehicle, so I can send a worker out to collect the vehicle and bring it back
Context 2 -- I want to know the axle and tire, because I am at the vehicle trying to do the work
You could flatten out the loops by using Java 8 streams.
vehicles.stream()
.flatMap(vehicle -> vehicle.getAxles().stream())
.flatMap(axle -> axle.getWheels().stream())
.flatMap(wheel -> wheel.getTires().stream())
.filter(tire -> tire.width == targetWidth
&& tire.diameter == targetDiameter)
.forEach(tire -> {
// do something
});
The nice thing about streams is that you could insert additional filter, filter, findAny, etc., calls pretty easily anywhere in the sequence.
I would inverse your logic and move the question into the Vehicle, unless of course you'd like to keep your objects thin for any other reason (in which case I'd personally wrap them with a thicker object to add any behaviour needed)
class Vehicle {
...
public Tire acceptsTire(Tire tire) {
}
}
from here on there are several possibilities, depending on how important this piece of business logic is in your domain in general.
If you'll have several actions you could probably just iterate as you had done in your sample. Or possibly in the same way as I suggested, keep cascade the question to the correct component. As long as you can live with the time complexity of doing this that should be alright.
If this check is something you'd usually do then you could have a reference to the type of tires you hold in the vehicle directly, this could be either your Tire collection, or you could pass a TireSpecification instance when constructing the Vehicle if for any reason you need to keep these separated (Your intention is not very clear in the question, is the tire on the car or just an spec of what could fit?)
Without changing your data structure you won't be able to make significant difference. You can add some syntactic sugar with lambdas, but it is essentially the same solution.
Things you could look at:
Your model allows for Vehicles with zero axles or hundred. While it depends on your business model it seems to weird.
Your model allows to have different axles in your vehicle, different wheels. Is it really necessary? Make sure which elements of your model should have their separate identity (currently each object has it) and which is just a value object.
Make sure you really need such detailed model. Currently you have two classes (Axle,Wheel), which only hold collections of inner objects. If they will be just simple JavaBean object with getAllInnerTypes() then you should consider removal of this class. It may even be the case that tire information should be stored almost directly in Vehicle class.
As long as there aren't too many items and/or performance is not a big issue, I would probably just go with the nested loops (or streams from John's answer).
Since you have two contexts for the search, you could pass the appropriate action to the search method - something like this (using loops in this case):
interface TireAction {
void doSomething(Vehicle v, Axle a, Tire t);
}
void findTireAndPerform(int targetWidth, int targetDiameter, TireAction action) {
for (Vehicle vehicle : vehicles) {
for (Axle axle : vehicle.getAxles()) {
for (Wheel wheel : axle.getWheels()) {
for (Tire tire : wheel.getTires()) {
if (tire.width == targetWidth && tire.diameter == targetDiameter) {
action.doSomething(vehicle, axle, tire);
break;
}
}
}
}
}
}
void someMethod() {
...
findTireAndPerform(width, diameter, (v, a, t) -> {
// send worker to 'v'
});
...
findTireAndPerform(width, diameter, (v, a, t) -> {
// work on 'a' and 't'
});
}
I have an object like:
class House {
String name;
List<Door> doors;
}
what I want to do is to tranform a List<House> to a List<Door> containing all doors of all houses.
Is there a chance to do this with guava?
I tried with guava used Lists.transform function but i only getting a List<List<Door>> as result.
If you really need to use a functional approach, you can do this using FluentIterable#transformAndConcat:
public static ImmutableList<Door> foo(List<House> houses) {
return FluentIterable
.from(houses)
.transformAndConcat(GetDoorsFunction.INSTANCE)
.toImmutableList();
}
private enum GetDoorsFunction implements Function<House, List<Door>> {
INSTANCE;
#Override
public List<Door> apply(House input) {
return input.getDoors();
}
}
FluentIterable.from(listOfHouses).transformAndConcat(doorFunction)
would do the job just fine.
You don't need Guava for it (assuming I understood you correctly):
final List<Door> doorsFromAllHouses = Lists.newArrayList();
for (final House house : houses) {
doorsFromAllHouses.addAll(house.doors);
}
// and doorsFromAllHouses is full of all kinds of doors from various houses
Using Lists.transform for input list of houses and transform function get all doors from a house gave you correct output of list of *each house's doors* (which is exactly List<List<Door>>).
More generally you want reduce / fold function instead of transform, which isn't implemented in Guava (see this issue), mostly because Java's verbose syntax and presense of for-each loop which is good enough. You'll be able to reduce in Java 8 (or you are able to do this in any other mainstream language nowadays...). Pseudo-Java8-code:
List<Door> doors = reduce(
houses, // collection to reduce from
new ArrayList<Door>(), // initial accumulator value
house, acc -> acc.addAll(house.doors)); // reducing function
I have a Product object. The Product is taxed at different rates in different places/situations.
Some of the products are not taxable at all (Example : Medicine)
For example , buying the product may cost $X in shop A and $Y at shop B . It can cost differently in two different states(state taxes are different).
My question is , can we have the attributes to determine the taxes inside the Product object itself.
For example is it a good idea to have attributes such as
Boolean isImported ;
Boolean isTaxable ;
Or do we have a better design pattern to do this ?
First of all, I believe there is no single, good answer to this question.
You can have the attributes to determine the taxes inside a Product. However, I would recommend to have a separate class (TaxCalculator?) that would calculate the tax of a Product based on its origin, type, transaction, etc. The motivation is that the Product should represent a product data only; why should e.g. a bottle of wine care what are the taxes assigned to it? Something else should do it, something that is specialised in calculating the tax based on the product.
But that is only my opinion and I do not claim it is the best one. I would like to hear from some more experienced users.
Products need not to know about the tax. Tax is logically related to a sale, so is the product price. In our app we have the following (simplified):
public class Invoice {
private InvoiceItem[] invoiceItems;
}
public class InvoiceItem{
private ProductPrice productPrice;
private BigDecimal taxRate;
}
public class ProductPrice{
private Product product;
private BigDecimal price;
private String currencyCode;
}
public class Product{
....
}
You can certainly put those attributes in the Product class.
Or you can create a separate interface (TaxStrategy?) that would take a Product and return a Money tax amount:
public interface TaxStrategy {
Money calculateTax(Product p);
}
That way you can have different implementations of the interface that compute taxes in different ways. Products need not know that they're taxable. It separates the thing that you sell from the way that you price it.