I would like to sort 2D nodes (points) in two dimensions (x and y) and also to allow fast addition and deletion. I would say that this can be done by two linked lists, but found, that Java's LinkedList hides linkage from user. I.e. if I found some node and delete it from one list, I am unable to delete it fast from another.
Is this solveable or I need to write my own class supporting two dimensions of linkage?
To delete the same object from both lists create a wrapper class like so
class PointWrap{
int id = 0;
Point p = null;
public PointWrap( int inid, Point inp){
id = inid;
p = inp;
}
}
An insert would look like this
tree.put( new PointWrap( id++, point) );
When you iterate through to delete just save the id before the delete occurs. This way you can delete from the other list/tree as well.
I would make a compound data structure.
Will you be reading or writing more? If reading more, use an ArrayList; if writing more, use a LinkedList. Have this structure store int[ ] and enter the values as {x, y} and have this structure sort, after each insertion block, by x value only.
Additionally, maintain an array that is populated with y values, not upon insert, but upon sorting of the x-list have this array populated with the values that are actually in the x-list.
Put all of this into a single class and tie the methods together under 1 hood & holy encapsulation batman!
You can have the class return int[2] from a getByX() or getByY()
A question to ask yourself first is, "Do I absolutely need both lists sorted all the time, or only during read operation blocks?" If your answer is the latter, this will work just fine for you.
Another thing to consider, will you need a queue, deque, stack, or all random access?
Related
I have to write a method that traverses a huge object's contents which are spread across machines and need to return this:
starting index in the object's struct(ex: if it has 10 pieces/blocks I can return piece/block 3-7)
offset within the first piece
list/array of pair < id of each piece, size of each piece > (not map - I've been clearly told not to use Map or Map.Entry)
Quoting exact words, I'm required to return fully-allocated array corresponding to the block range.
Thought #1: The starting index and offset are to be returned once, the option to create a class with
index
offset
id
size
and returning an array of this will be providing redundant information plus, adding 8 bytes every entry is huge waste of memory.
Thought #2: I could create a data class with (id and size) and return another class with array of this smaller class + index & offset, but in this case the existence of my data class will be just to contain values which doesn't seem v. prudent.
Thought #3:I've heard multiple times that people resort to arrays when need to return pairs. I don't know how to do that?
You have to create, basically, a data structure. There is a single way to do that in Java: use classes.
Your first thought is wrong: you must return a single index, and a single offset, and multiple pairs. It's thus wrong to put all the fields in a single class, since the cardinality of the fields is not the same. In particular, if there is 0 pair to return, you would be very embarrassed.
Your second thought maps exactly to what you must return. Except I would use a collection (List or Set) instead of an array:
public class Result {
private int index;
private int offset;
private Set<Piece> pieces;
...
}
public class Piece {
private String id;
private int size;
...
}
Why use a collection rather than a Piece[] array: because there's a good chance that you don't know the number of pieces before the traversal. Because a List or Set has many useful methods that an array doesn't have. Because a Set<Piece> clearly says that there are no duplicate elements, which is not the case with an array of Piece.
The third thought consists in using an Object[] containing 2 elements (or an int[] of two elements, if both the ID and the size are of type int, for example), to hold the information about a Piece. But that is ugly and unreadable: it's not obvious at all what the array contains, in which order, and what their type is. And you can't add any useful method like you could with a Piece class.
Java is an OO language. Use classes and objects. Use encapsulation.
I want to create a large matrix (n by n) where each element corresponds to a LinkedList (of certain objects).
I can either
Create the n*n individual linked lists and name them with the help of eval() within a loop that iterates through both dimensions (or something similar), so that in the end I'll have LinkedList_1_1, LinkedList_1_2 etc. Each one has a unique variable name. Basically, skipping the matrix altogether.
Create an ArrayList of ArrayLists and then push into each element a linked list.
Please recommend me a method if I want to conserve time & space, and ease-of-access in my later code, when I want to reference individual LinkedLists. Ease-of-acess will be poor with Method 1, as I'll have to use eval whenever I want to access a particular linked list.
My gut-feeling tells me Method 2 is the best approach, but how exactly do I form my initializations?
As you know the sizes to start with, why don't you just use an array? Unfortunately Java generics prevents the array element itself from being a concrete generic type, but you can use a wildcard:
LinkedList<?>[][] lists = new LinkedList<?>[n][n];
Or slightly more efficient in memory, just a single array:
LinkedList<?>[] lists = new LinkedList<?>[n * n];
// Then for access...
lists[y * n + x] = ...;
Then you'd need to cast on each access - using #SuppressWarnings given that you know it will always work (assuming you encapsulate it appropriately). I'd put that in a single place:
#SuppressWarnings("unchecked")
private LinkedList<Foo> getList(int x, int y) {
if (lists[y][x] == null) {
lists[y][x] = new LinkedList<Foo>();
}
// Cast won't actually have any effect at execution time. It's
// just to tell the compiler we know what we're doing.
return (LinkedList<Foo>) lists[y][x];
}
Of course in both cases you'd then need to populate the arrays with empty linked lists if you needed to. (If several of the linked lists never end up having any nodes, you may wish to consider only populating them lazily.)
I would certainly not generate a class with hundreds of variables. It would make programmatic access to the lists very painful, and basically be a bad idea in any number of ways.
I would like to know how to create a structure to hold three lists in the following format:
[[[x],[y]],[z]]
with x,y,z being three lists of strings.
Note that I want to have the x and y lists on the 3rd level down and the z list on the 2nd level down.
I have tried creating 3 separate arraylists for x,y and z then another arraylist that holds x and y. The problem arise when I tried to create the outer most arraylist to hold all three, because something like
ArrayList<ArrayList<ArrayList<String>>> outerList = new ArrayList<ArrayList<ArrayList<String>>>();
would work for x and y but wont work for z because z is only 2 levels down.
I understand what I'm trying to do is more like a tree but I do not know how to implement a non-binary tree in java (x,y,z having more then just 2 branches).
What I'm trying to get out of this is a way to assign weights eg. user inputs a term, I iterate first through all the child nodes (x,y,z) and try to find it. If I find it I assign a high weight, otherwise I try to find it in the parent nodes (the list that holds x,y) and give it a moderate weight else I search in the root node and assign a minimum weight. The structure described is simply the relationship between the terms that I have categorized.
Any ideas on how to do this?
This is where the power of objects comes in. You could create a class which contains the list of xs and ys, then create another class which holds a list of that class along with your list of xs. Finally you have a list of those classes.
If you want to get clever about it, try inheriting from ArrayList and overriding or overloading its methods to do what you need. http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
You also mentioned doing it in a tree manner. To do that there are some good suggestions here: Java tree data-structure?
The structure is easy enough to make, but working with it will be really ugly because you don't know how deep it goes. If this is a set structure, where you only ever have x, y, and z, you should make a custom object to handle that known structure. If you won't know the structure until runtime, then you need something like this.
Note that while this structure does match what you asked for, I don't necessarily recommend using it unless you have to. Look for alternatives. You mentioned a tree, but from your structure this would be a tree with data only at the leaf nodes, so keep that in mind if/when you implement it.
public void useArrayList()
{
ArrayList<ArrayList<?>> weirdStructure = new ArrayList<ArrayList<?>>();
ArrayList<String> x = new ArrayList<String>();
ArrayList<String> y = new ArrayList<String>();
ArrayList<String> z = new ArrayList<String>();
ArrayList<ArrayList<String>> xy = new ArrayList<ArrayList<String>>();
xy.add(x);
xy.add(y);
weirdStructure.add(xy);
weirdStructure.add(z);
}
So far I have what's written below but how would I make sure the item to add returns to it's alphabetized spot?
I'm in a beginner class so I cannot use ArrayLists or the methods assoicated with them.
Any sort of help or push in the right direction would be appreciated. Thanks!
The method should follow these instructions:
- Adds an item to the list. This method assumes that the list is already
sorted in alphabetical order based on the names of the items in the list.
- The new item will be inserted into the list in the appropriate place so
that the list will remain alphabetized by names.
In order to accommodate the new item, the internal array must be re-sized
so that it is one unit larger than it was before the call to this method.
public void add(Listable itemToAdd) {
Listable[] items1;
int newlength = items.length+1;
items1 = new Listable [newlength];
for(int i = 0;i<items.length;i++){
items1[i] = items[i];
items1[newlength-1] = itemToAdd;
}
}
That's not bad for a start! There are a number of things we need to do. This line
items1[newlength-1] = itemToAdd;
needs to come out of the loop, and be placed afterwards -- you'll set some array element to this value just once, yes, and not many times?
The copying part is a good start. What you need to do is
Find the location where the new element should go (search through the array, and find the element that the new one should go after)
Copy the elements that go before the new element
Copy the new element
Copy the elements that go after the new element (adjusting their indexes, since they're all one later than they used to be!)
Make sense?
If you're in a beginner class, you may have learned about insertion sort. One of the interesting properties of insertion sort is that despite its poor runtime in the average case (O(n2)), its performance in the best case (a sorted list) is quite good - O(n), in fact. An almost-sorted list would run in the same efficiency class. That might be a way to accomplish what you're trying to do. (It also might be one of the few places you'll ever use insertion sort, so make the most of it.)
Although I have Java in the title, this could be for any OO language.
I'd like to know a few new ideas to improve the performance of something I'm trying to do.
I have a method that is constantly receiving an Object[] array. I need to split the Objects in this array through multiple arrays (List or something), so that I have an independent list for each column of all arrays the method receives.
Example:
List<List<Object>> column-oriented = new ArrayList<ArrayList<Object>>();
public void newObject(Object[] obj) {
for(int i = 0; i < obj.length; i++) {
column-oriented.get(i).add(obj[i]);
}
}
Note: For simplicity I've omitted the initialization of objects and stuff.
The code I've shown above is slow of course. I've already tried a few other things, but would like to hear some new ideas.
How would you do this knowing it's very performance sensitive?
EDIT:
I've tested a few things and found that:
Instead of using ArrayList (or any other Collection), I wrapped an Object[] array in another object to store individual columns. If this array reaches its capacity, I create another array with twice de size and copy the contents from one to another using System.copyArray. Surprisingly (at least for me) this is faster that using ArrayList to store the inner columns...
The answer depends on the data and usage profile. How much data do you have in such collections? What is proportions of reads/writes (adding objects array)? This affects what structure for inner list is better and many other possible optimizations.
The fastest way to copy data is avoid copying at all. If you know that obj array is not modified further by the caller code (this is important condition), one of possible tricks is to implement you custom List class to use as inner list. Internally you will store shared List<Object[]>. Each call we just add new array to that list. Custom inner list class will know which column it represents (let it be n) and when it is asked to give item at position m, it will transpose m and n and query internal structure to get internalArray.get(m)[n]. This implementation is unsafe because of limitation on the caller that is easy to forget about but might be faster under some conditions (however, this might be slower under other).
I would try using LinkedList for the inner list, because it should have better performance for insertions. Maybe wrappping Object arra into collection and using addAll might help as well.
ArrayList may be slow, due to copying of arrays (It uses a similar approach as your self-written collection).
As an alternate solution you could try to simply store the Rows at first and create columns when neccessary. This way, copying of the internal arrays at the list is reduced to a minimum.
Example:
//Notice: You can use a LinkedList for rows, as no index based access is used.
List<Object[]> rows =...
List<List<Object>> columns;
public void processColumns() {
columns = new ArrayList<List<Object>>();
for(Object[] aRow : rows){
while (aRow.size() > columns.size()){
//This ensures that the ArrayList is big enough, so no copying is necessary
List<Object> newColumn = new ArrayList<Object>(rows.size())
columns.add(newColumn);
}
for (int i = 0; i < aRow.length; i++){
columns.get(i).add(aRow[i]);
}
}
}
Depending on the number of columns, it's still possible that the outer list is copying arrays internally, but normal tables contains far more rows than columns, so it should be a small array only.
Use a LinkedList for implementing the column lists. It's grows linearly with the data and is O(1). (If you use ArrayList it has to resize the internal array from time to time).
After collecting the values you can convert that linked lists to arrays. If N is the number of rows you will pass from holding 3*N refs for each list (each LInkedList has prevRef/nextRef/itemRef) to only N refs.
It would be nice to have an array for holding the different column lists, but of course, it's not a big improvement and you can do it only if you know the column count in advance.
Hope it helps!
Edit tests and theory indicate that ArrayList is better in amortized cost, it is, the total cost divided by the number of items processed... so don't follow my 'advice' :)