DESIGN PROBLEM: How to use composition the best - java

I'm working on a project and have some doubts about it's design.
How can I design the following problem the best (in JAVA):
Class A with the following attributes:
HashSet of Pixels where each pixel has x,y coordinates and value v between 0-1.
instance of class B.
Class B with the following function:
a function that gets a Pixel and returns its left neighbor.
When I'm in class A I want to use B.function on each pixel in A and add it to the HashSet only if it's not already there. The problem is that I don't want to send the HashSet to the function, how bad is it to return new instance of Pixel from the function if it might already exist (This function going to run on many pixels and will create many unused instances of Pixel).
What other options do I have?

Since you use Set<Pixel> you have to create new Pixel instance to check if it exists in set or not.
If set contains N elements after calling B.function method you will create extra N Pixel nodes. If all elements are new, you just add them to set, in other case Garbage Collection needs to sweep them. One of drawbacks is we need to create m (wheren m <= N - number of Pixel-s which already exists in set) and later we need to collect them by GC. How big is m/N ratio depends from your algorithm and what you are actually doing.
Lets calculate how many memory we need to consume for N = 1_000_000 pixels in set. We know that int is a 4 bytes and double is 8 bytes, lets add extra 8 bytes for an object and 8 bytes for a reference. It gives 32 bytes for every instance of Pixel object. We need to create N objects which gives 32MB. Let's assume that our ratio is 50% so, 16MB we allocated just to check it is not needed.
If this is a cost you can not pay you need to develop algorithm which allows you iterate over Set<Pixel> in an order from left-to-right. So, left neighbour of Pixel X is before X.
Assume that left neighbour of Pixel X(x, y) is pixel X'(x - 1, y). Pixel B(0, y) does not have left neighbour. You need to use TreeSet and implement Comparable<Pixel> interface in Pixel class. Simple implementation could look like this:
#Override
public int compareTo(Pixel o) {
return this.y == o.y ? this.x - o.x : this.y - o.y;
}
This allows you to iterate set in order from left to right: (0, 0), (1, 0), ...., (x - 1, y), (x, y), (x + 1, y), ... , (maxX, maxY). So, when you iterate it you can check whether previous element is a left neighbour of current Pixel. Example implementation could look like below:
void addNeighboursIfNeeded() {
Set<Pixel> neighbours = new HashSet<>(pixels.size());
Pixel last = null;
for (Pixel p : pixels) {
if (p.getX() == 0 || p.isLeftNeighbour(last)) {
// a left border pixel
// or last checked element is a left neighbour of current pixel.
last = p;
continue;
}
// last element was not our left-neighbour so we need to call b method
Pixel left = b.getLeft(p);
neighbours.add(left);
last = p;
}
// add all new neigbours
pixels.addAll(neighbours);
}
This should allow you to save this memory which is allocated for duplicated Pixel objects.

I can see here few concerns regarding object oriented programming.
Encapsulation violation: When you call function of B from A which operates on A's data (which you are avoiding by not sending HashMap), it violates encapsulation (If there is a reason, its acceptable though). Is it possible to move that function (operating on A's HashSet) to A? This will protect A's state from getting exposed.
Proliferation of classes: There is a possibility that there will be large number of objects of Point type. You can think of using Flyweight GOF design pattern, it will externalize the state of each point and will make it reusable. and will reduce number substantially.
Passing large collection of Points to method in B: If you can shift method from B to A, this point gets resolved. Anyway java will pass this collection by reference. But in that case its open for modifications from external classes (need to take care of this aspect).
Abstraction of type Point: If class Point has only state and no behavior, it will lead to violation of encapsulation. Can you shift the method getNeighbour() in to Point? as it will make Point immutable (which is essential). Off course actual algorithm can be delegated to another class (if its independently varying responsibility and has hierarchy of algorithms, think of GOF Strategy pattern here).
Uniqueness of points in collection: which your set will take care with due care about appropriate Hash and logical equality for class Point.

Related

Fastest way to check which rectangle is clicked in a list of rectangles

I have a rectangle Object with x, y, width and height. I have a list of these rectangles which are displayed on a screen. It is guaranteed that none of them overlap. Given a user's click position (x and y coordinates), I want to see which of these rectangles were clicked (since they do not overlap, there is a maximum of one rect that can be clicked).
I can obviously look through all of them and check for each one if the user clicked it but this is very slow because there are many on the screen. I can use some kind of comparison to keep the rectangles sorted when I insert a new one into the list. Is there some way to use something similar to binary search in order to decrease the time it takes to find which rect was clicked?
Note: the rectangles can be any size.
Thanks:)
Edit: To get an idea of what I am making visit koalastothemax.com
It highly depends upon your application and details we're not quite aware of yet for what the best solution would be. BUT, with as little as I know, I'd say you can make a 2D array that points to your rectangles. That 2D array would map directly to the pixels on the screen. So if you make the array 10x20, then the coordinate x divided by screen width times 10 (casted to int) will be the first index and y divided screen height times 20 would be your y index. With your x and y index, you can map directly to the rectangle that it points to. Some indexes might be empty and some might point to more than one rectangle if they're not perfectly laid out, but that seems the easiest way to me without knowing much about the application.
I have tackled a very similar problem in the past when developing a simulation. In my case the coordinates were doubles (so no integer indexing was possible) and there could be hundreds of millions of them that needed to be searched.
My solution was to create an Axis class to represent each axis as a sequence of ranges. The ranges were guaranteed to go from a minimum to a maximum and the class was smart enough to split itself into pieces when new ranges were added. Each range has a single generic object stored. The class used a binary search to find a range quickly.
So roughly the class looks like:
class Axis<T> {
public Axis(double min, double max, Supplier<T> creator);
public Stream<T> add(double from, double to);
public T get(double coord);
}
The add method needs to return a stream because the added range may cover several ranges.
To store rectanges:
Axis<Axis<Rectangle>> rectanges = new Axis<>(0.0, 100.0,
() -> new Axis<>(0.0, 100.0, Rectangle::new));
rectangles.add(x, x + w).forEach(r -> r.add(y, y + h).forEach(Rectangle::setPresent));
And to find a rectangle:
rectangles.get(x).get(y);
Note that there's always an object stored so you need a representation such as Rectangle.NULL for 'not present'. Or you could make it Optional<Rectangle> (though that indirection eats a lot of memory and processing for large numbers of rectangles).
I've just given the high level design here rather than any implementation details so let me know if you want more info on how to make it work. Getting the logic right on the range splits is not trivial. But I can guarantee that it's very fast even with very large numbers of rectangles.
The fastest way I can come up with is definitely not the most memory efficient. This works by exploiting the fact that an amortized hash table has constant lookup time. It will map every point that a rectangle has to that rectangle. This is only really effective if your are using integers. You might be able to get it to work with floats if you use a bit of rounding.
Make sure that the Point class has a hash code and equals function.
public class PointCheck
{
public Map<Point, Rect> pointMap;
public PointCheck()
{
pointMap = new HashMap<>();
}
/**
* Map all points that contain the rectangle
* to the rectangle.
*/
public void addRect(Rect rect)
{
for(int i = rect.x; i < rect.x + rect.width; ++i)
{
for(int j = rect.y; j < rect.y + rect.height; ++i)
{
pointMap.put(new Point(i, j), rect);
}
}
}
/**
* Returns the rectangle clicked, null
* if there is no rectangle.
*/
public Rect checkClick(Point click)
{
return pointMap.get(click);
}
}
Edit:
Just thought I should mention this: All of the rectangles held in the value of the hash map are references to the original rectangle, they are not clones.

Optimally searching for 2D points in the given area (webservice)

I've got a kind of algorithmic & performance problem to solve with Java. I've got a large collection of 2D points (let's say there are about 100 000 of them). I want to get a set of them that are in the given area around the search point SP(X_sp, Y_sp), so that I'd like to get the points P(x y) that meets the criteria:
x is between X_sp - constValue and X_sp + constValue AND y is between Y_sp - constValue and Y_sp + constValue
To give you an idea of the number relations, constValue will be like 2, 5 or 10, and x, y will range between 0 and 1000. It's meant to be a webservice, so a possibility of searching around many different points at the same time must be taken into account.
As these are fixed points (not to change due to calculations or something), I thought that it would be optimal to provide one list of objects sorted by X and another one, but sorted by Y. Then, I'll first get the points within the X range, and, using references, get the set of this points from another list (sorted by Y). Then I'll narrow this selection by Y and in result get the points in the given area.
I don't know Java inside-out, so I'd like to consult with you the most optimized approach. Which objects should I use to store sorted points, which allow for fast search of objects within range? Or maybe I have to implement my custom algorithm for this task? Also, when it comes to storing the points in the database, are SQL queries sufficiently fast to deliver the results? Or maybe NoSQL dbs are better for this?
I'm going to perform my own tests, but I'm looking for a starting candidates.
I'd probably use a TreeMap<Integer, TreeSet<Integer>>, where the key to the map is the x coordinate and for each x coordinate, you have a list of y coordinates. You can then use floorEntry and ceilingEntry to find the x coordinates that fall within your range. Then for each TreeSet<Integer> set that you get, you can use ceiling and floor to get the appropriate entries.
Of course, this only gives you the coordinates of the bounds of your box (the four corners). But TreeSet also has a subset that will give you a range of values. You will have to use this twice; once for the list of x coordinates (you can get the key set using the keySet method of the map) that are within your bounds, then for each x coordinate, the y coordinates that are within the bounds. So the pseudocode would be sort of like this:
List<Point> result = new ArrayList<>();
int lowerX = points.ceilingKey(x - c);
int upperX = points.floorKey(x + c);
for each x coordinate in points.entrySet().subset(lowerX, upperX)
TreeSet<Integer> yCoordinates = points.get(x);
lowerY = yCoordinates.ceiling(y - c);
upperY = yCoordinates.ceiling(y + c);
for each y coordinate in yCoordinates.subset(lowerY, upperY)
result.add(new Point(x, y))
I haven't tested this out, so there are probably some bugs or something I've missed. Let me know and I'll correct the answer.
The floor and ceiling calls are log(n) I believe -- this is where you get the performance benefit because if you use a list, it would be O(n) to look that up.
Note: I don't know if this is the most performant. SO is typically not the place for such an open-ended question so you might have more luck elsewhere.

java - search sorted list of rectangles

I have a list of Rectangles, created in the usual way with:
List<Rectangle> rects = new ArrayList<>();
Some Rectangles are added (all with non-zero width and height). The number of Rectangles the List contains can be anywhere between 0 and 10,000, and will typically be between 4,000 and 6,000.
The list is sorted by ascending X-coordinate of the Rectangle origin, and then by ascending Y-coordinate for duplicate X-coordinates (though two or more rectangles with the same X-coordinate is rare).
I've verified the sorting is being done correctly (I'm using Collections.sort with a custom comparator).
I need a method that takes as input two ints, x and y, and returns the first Rectangle found containing the point (x,y), or null if no Rectangle in the list contains that point.
public Rectangle findContainingRectangle(int x, int y)
The naive method, which does give the desired functionality, is to just loop through the list and call the contains method on each Rectangle, but that is much too slow.
The List will be modified while the program is running, but at an insignificant rate compared to the rate at which the List needs to be searched, so an algorithm that requires a relatively slow initialization is fine.
I've looked at Collections.binarySearch but couldn't figure out how it might be used. I don't have much experience with Java so if there's another Collection that could be used similarly to a List but better suited to the type of search I need, then that's great (I have read the documentation on things like Maps and Sets but didn't recognize any advantage).
While maintaining a sorted list, you could use a binary search on the 'X' coordinate to find the candidates of the rectangles that contain the wanted 'X', and after which, use binary search on the 'Y' coordinate.
You should implement the binary search yourself, I can't see a way you can use the Collections.binarySearch method.
expected complexity: O(log n) as n the number of rectangles.
(It's a bit more because you might have duplicates)
However ,to do so, you should keep the array sorted while adding other instances, (sort after every insert).
Use HashSet. Map isn't appropriate here since you're not creating key-value pairs, and a Stream doesn't fit in this context either.
Be sure to override equals() and hashCode() in Rectangle, as described here: Why do I need to override the equals and hashCode methods in Java?
You can search your list using parallel stream like this
public Rectangle findContainingRectangle(final int x, final int y) {
List<Rectangle> rectangles = new ArrayList<>();
Rectangle rec = rectangles.parallelStream().filter((r)->{
if(r.getX()==x && r.getY()==y){
return true;
}
return false;
}).findFirst().get();
return rec;
}
Just run binary search a bunch of times - since the probability of same x is low as you say it wont take many times so it will still be logn
a) run binary search
b) remove item if found - and keep index where it was found
c) repeat binary search at a) with the remaining list until null is returned
d) then you have a small array of indexes and you can see which one is the smallest
e) then reinsert the removed elements at the designated spots
You can try and see a performance of a stream. I am not sure it will be fast enough but you can test it.
Rectangle rec = rects.stream().filter((r)->{
return r.contains(x, y);
}).findFirst().get();
You can create a Map.
Map is the best way to associate two values. You can associate the 'x' value and its first position in your List. Then you only have to loop from the first 'x' position to another 'x' in your list.
If you don't find the 'x' on the Map, they don't have the good rectangle on your list.
With this way you don't explore all bad 'x' entry.

Can Java Comparable<Object> fail on a max/min cross-comparison?

I've working on a depth sorting problem, here's an example case I constructed
There are two planes, one hovering above the other, and they are sectioned into rectangluar polygons. Each polygon is defined by it's 'real-world' coordinates, as well as defined with a camera and view projections to produce a perspective view, as shown. A trace-printout of an example polygon produces
Zn = -0.225, Zf = -0.432
v0 (13, 33, 32.7) (-0.358, -0.065, -0.295, 180.737)
v1 (29, 33, 32.7) (-0.192, -0.142, -0.225, 173.247)
v2 (29, 33, 7.2) ( 0.011, 0.023, -0.375, 190.239)
v3 (13, 33, 7.2) (-0.148, 0.087, -0.432, 197.730)
This sample is one belonging to the green plane y=33, the non-projected vertices are v0 to v4 = (13,33,32.7),(29,33,32,7),(29, 33,7.2) and (13,33,7.2)
The projected coordinates, using a standard camera and view model, are shown following. If p(i) is the projected coordinate then -1 < p(i).x,p(i).z,p(i).z < 1. The fourth value is the homogenous W coordinate when prepared for rendereding divided into each p(i)(x,y,z), it is preserved as a reference value because it gives the distance from the 'camera' to a perpendicular plane of a given vertex.
The third column in the second series of brackets are the projected Z-values, and importantly for this problem The values Zn=depth of nearest vertex, and Zf=depth of farthest vertex
The question
This question is motivated by all of the above but is also independent of any knowledge of graphics rendering. My motivation is to depth-sort the quadrilateral polygons primarily on their Z-values
According to Painter's algorithm the first check on rendering order between two polygons is if the Z-near and Z-far are separate and should imply unambiguous spacial separation.
A simplified extract of the comparison
class Extent implements Comparable<Extent> {
double Zn;
double Zf;
#Override
public int compareTo(Extent ext2) {
if (Zn < ext2.Zf) return 1;
if (ext2.Zn < Zf) return -1;
return 0;
}
}
My Problem
When I run the comparison against a large set of polygons, sometimes I get a
java.lang.IllegalArgumentException: Comparison method violates its general contract exception. While often the rendering looks good as above, sometimes it fails. But why, I haven't been able to find a fail-case, and shouldn't comparing on two max,min in this way always be transient?
Does anyone know of an example set that would fail, subjected to this comparison? And, perhaps, are you able to spot a logical error in my method? (while insight in the internals of the compare method is the primary enquiry, if you are familiar with 3d depth-sorting please feel free to comment)
You should use an external Comparator to compare with instead of trying to implement Comparable which for complex objects is almost always the wrong way to do it.
Comparable works great for objects with a single or very few attributes that need to be the same in all cases. Like a complex object with an ID that is unique which is the only thing that is compared.
It does not work for complex cases where all the attributes are not considered in all cases. For those times you use a Comparator or better yet Ordering from the Guava library so that you can do elegant chaining and compositions.
Also sorting on triangles makes this exercise trivial because they can never be non-planar and have one less point to compare.
Your algorithm won't satisfy the compareTo contract, because of transitivity failure; you're not defining a total ordering. Consider three Extents
p1(0,3) p2(0,1) p3(2,3)
The implementor must ensure that p1.compareTo(p2) == 0 implies that
sgn(p1.compareTo(p3)) == sgn(p2.compareTo(p3)) for all other points.
p1.compareTo(p2) is 0.
p1.compareTo(p3) is 0, but p2.compareTo(p3) is -1.
The "best" way to sort ranges will depend on what exactly you want to do with the sorted list, but you'll most likely end up sorting on either the near, far, or center values.

Special kind of queue

I am looking for something like a Queue that would allow me to put elements at the end of the queue and pop them out in the beginning, like a regular Queue does.
The difference would be that I also need to compact the Queue from time to time. This is, let's assume I have the following items on my Queue (each character, including the dot, is an item in the Queue):
e d . c . b . a
(this Queue has 8 items)
Then, I'd need for example to remove the last dot, so to get:
e d . c . b a
Is there anything like that in the Java Collection classes? I need to use this for a program I am doing where I can't use anything but Java's classes. I am not allowed to design one for myself. Currently I'm just using a LinkedList, but I thought maybe this would be more like a Queue than a LinkedList.
Thanks
edit:
Basically here is what the project is about:
There is a traffic light that can be either green(and the symbol associated is '-') or red('|'). That traffic light is on the right:
alt text http://img684.imageshack.us/img684/9602/0xfhiliidyxdy43q5mageu0.png
In the beggining, you don't have any cars and the traffic light is green, so our list is represented as:
....... -
Now, on the next iteration, I have a random variable that will tell me wherever there is a car coming or not. If there's a car coming, then we can see it appearing from the left. At each iteration, all cars move one step to the right. If they have any car directly on their right, then they can't move:
a...... - (iteration 1)
.a..... - (iteration 2)
..a.... - (iteration 3)
etc.
Now, what happens is that sometimes the traffic light can turn red('-'). In that case, if you have several cars, then even if they had some distance between them when moving, when they have to stop for the traffic light they will get close:
...b.a. - (iteration n)
....b.a - (iteration n+1)
.....ba - (iteration n+2) here they got close to each other
Now, that is the reason why this works like a Queue, but sometimes I have to take down those dots, when the cars are near the red traffic light.
Keep also in mind that the size of of the street here was 7 characters, but it sometimes grows, so we can't assume this is a fixed length list.
A queue is basically a list of items with a defined behavior, in this case FIFO (First In First Out). You add items at the end, and remove them from the beginning.
Now a queue can be implemented in any way you choose; either with a linked-list or with an Array. I think you're on the right path. A linked list would definitely make it easier.
You'll have O(1) for the add and the remove with your queue (if you maintain a reference to the front and the back), but the worst-case scenario for compacting (removing the dot) would be O(n).
I believe there might be a way to reduce the compact operation to O(1) (if you're only removing one dot at a time) if you use a secondary data structure. What you need is another queue (implemented using another linked-list) that maintains a reference to dots in the first linked list.
So, when you insert (a, ., b, c, ., d) you have a list that looks like:
[pointer to rear] -> [d] -> [.] -> [c] -> [b] -> [.] -> [a] <- [pointer to front]
and you also have a secondary queue (implemented as a linked list) that maintains a reference to the dot:
[pointer to rear] -> [reference to second dot] -> [reference to first dot] <- [pointer to front]
Then, when you need to perform a compact operation, all you have to do is remove the first element from the second queue and retain the reference. So you now have a reference to a dot that is in the middle of the first linked list. You can now easily remove that dot from the first list.
You mentioned in a comment that you need to keep track of the order. A queue by definition is an ordered structure (in the sense that things remain in the order they were inserted). So all you need to do is insert a reference to the dot into the second queue when you insert a dot into the first. That way, order is maintained. So when you pull off a reference to a dot from the second queue, you have a reference to the actual and corresponding dot in the first queue.
The trade-off here for speed is that you need more memory, because you're maintaining a second list of references. Worst-case memory requirement is 2x what you're using now. But that is a decent trade-off to get O(1) vs O(n).
Homework exercises/school projects are always tricky, adding subtle stuff to the requirements that may make someone's brain melt down. Do you have any requirement to include the spaces as part of the queue?
Personally, I wouldn't do that unless explicitly required: it seems simpler to represent your cars as Car, Space pairs, (you can define the pair as a struct, assuming you are allowed to use structs) where space is a numeric value representing the space towards the next car in the vehicle. Then, to compact, you only need to look through the list items: when you find one that has Space > 0, do Space--; return;, and all other cars will have already "advanced", as they keep the space with the ones in front of them. In order to output, make sure to toss out Space dots for each car after (if the stoplight is at the right and the cars come from the left) or before (stoplight at left and cars coming from right) the car itself, and there you go. Also note that the Space of the first car represents the distance to the stoplight itself, since it has no car before it.
If you add to the struct a pointer to the next car (and a null pointer for the last car), you already have a linked list: keep a "global" variable that points to the first car (or null for an empty queue). Since Java doesn't directly supports pointers, turn the struct into a class and use "object references" (which are the same as pointers for all purposes other than C'ish pointer arithmetics), and there you go: only one class, built from scratch. The only thing you'll need to touch from Java's libraries is the standard IO and, maybe, a bit of string manipulation, which is an inherent need derived from having to take input and produce output (some colleges have their own course-specific IO libraries, but that doesn't make a big difference here). To loop through the queue you'd do something like this (assuming the class is named "Node", which is quite generic, and obvious names for the fields):
for(Node pos = First; pos != null; pos = pos.Next) {
/* Do your stuff here, knowing that "pos" points to the "current" item on each iteration. */
}
To add new nodes you probably have to traverse the queue to figure out at which distance from the last will the new car "spawn"; when you do so keep the reference from the last node and make its "next" reference point to the new node:
Node last = First;
int distance = 0;
for(Node pos = First; pos != null; pos=pos.Next) {
distance += pos.Space;
last = pos;
}
last.Next = new Node(the_letter_for_this_car, MaxDistance-distance, null);
Of course, tune the constructor to whatever you have.
Considering that this is a college project, let's take a look at some details: the compact process time becomes O(n) and it's memory usage is O(0) (the process itself doesn't need any "local" variables, other than maybe a pointer to traverse the collection which is independent from the length of the queue.) In addition, the memory usage for the queue itself is guaranteed to be smaller or equal to what it would be representing the spaces as items (it only gets to be equal on the worst scenario, when enough cars are stuck at a red light). So, unless the requirements include something incompatible with this approach, I'd expect this to be what your teachers want: it's reasoned, efficient, and compliant to what you were asked for.
Hope this helps.
I would say that a LinkedList would be the best approach here... as a LinkedList allows you to push/pop from the front/back and allows you to remove an item in the middle of the list.
Obviously, the lookup time sucks, but if you are adding/removing from the front/back of the list more often then looking up, then I'd say stick with the LinkedList.
Maybe a second LinkedList which keeps the dot element ?

Categories

Resources