I need to associate a unique key with each of a number of rectangle objects in Java. The key is in double data type, and the rectangles are obviously rectangle data types.
Currently, I have the rectangles in a vector, but they are not of much use to me unless I can also access their keys, as specified in the first paragraph above.
I would make a 2d array, with the first column being the key and the second column being the rectangle, but the number of rows in the array will need to change all the time, so I do not think an array would work. I have looked into vectors and arrayLists, but I am concerned about being able to search and slice the data.
Can anyone show me some simple java code for creating and then accessing a 2D data set with a variable number of rows?
Currently, my prototype looks like:
ArrayList<Double> PeakList = new ArrayList<Double>();
Vector<Rectangle> peakVector = new Vector<Rectangle>();
Vector<Double> keyVector = new Vector<Double>();
if(PeakList.contains((double)i+newStartingPoint)){
Rectangle myRect = new Rectangle(x2-5, y2-5, 10, 10);
boolean rectFound = peakVector.contains(myRect);
System.out.println("rectFound is: "+rectFound);
Double myPeak = ((double)i+newStartingPoint);
if(rectFound!=true){
peakVector.add(myRect);
keyVector.add(myPeak);
System.out.println("rectFound was added.");
}else{System.out.println("rectFound was NOT added.");}
}
I then enumerate through the data for subsequent processing with something like the following:
Enumeration e = peakVector.elements();
while (e.hasMoreElements()) {
g2.fillRect(peakVector.lastElement().x, peakVector.lastElement().y, 10, 10);
}
As you can see, there is no way to subsequently integrate the keys with the rectangles. That is why I am looking for a 2D object to use. Can anyone show me how to fix this code so that I can associate keys with rectangles and subsequently access the appropriately associated data?
Why not simply use a HashMap<Double, Rectangle>?
Edit: no, there are significant problems with this since there's no guarantee that two doubles will equal each other even though numerically they should. Does it have to be Double? Could use use some other numeric or String representation such as a Long? Is there a physical reality that you're trying to model?
Why not use a Map? They are specifically designed to associate keys with values. You can iterate through the keys of the map with keySet(), the values with valueSet() and both the keys and values at the same time with entrySet()
A Map will surely be the right answer, you don't worry about cardinality of the domain or of the codomain of the mapping function. Having double as the key datatype forbids you from using some of the predefined types.
I would go with a TreeMap<Double, Rectangle> just because the natural ordering is used to sort the entries inside the structure, so having a double is perfectly allowed, but you would have problems with the retrieval (I actually used myself floats as keys for maps and never had a problem with some precautions but it mostly depends on the nature of your data.
Related
In Java.
How can I map a set of numbers(integers for example) to another set of numbers?
All the numbers are positive and all the numbers are unique in their own set.
The first set of numbers can have any value, the second set of numbers represent indexes of an array, and so the goal is to be able to access the numbers in the second set through the numbers in the first set. This is a one to one association.
Speed is crucial as the method will have to be called many times each second.
Edit: I tried it with SE hashmap implementation, but found it to be slow for my purposes.
There's an article, devoted to this problem (with a solution): Implementing a world fastest Java int-to-int hash map
Code can be found in related GitHub repository. (Best results are in class IntIntMap4a.java )
Citation from the article:
Summary
If you want to optimize your hash map for speed, you have to do as much as you can of the following list:
Use underlying array(s) with capacity equal to a power of 2 - it will allow you to use cheap & instead of expensive % for array index
Do not store the state in the separate array - use dedicated fields for free/removed keys and values.
Interleave keys and values in the one array - it will allow you to load a value into memory for free.
Implement a strategy to get rid of 'removed' cells - you can sacrifice some of remove performance in favor of more frequent get/put.
Scramble the keys while calculating the initial cell index - this is required to deal with the case of consecutive keys.
Yes, I know how to use citation formatting. But it looks awful and doesn't handle bullet lists well.
The structure you are looking for is called an associative array. In computer science, an associative array, map, symbol table, or dictionary is an abstract data type composed of a collection of (key, value) pairs, such that each possible key appears just once in the collection.
In java in particular as already mentioned this is easily done with a HashMap.
HashMap<Integer, Integer> cache = new HashMap<Integer, Integer>();
You can insert elements with the method put
cache.put(21, 42);
and you can retrieve a value with get
Integer key = 21
Integer value = cache.get(key);
System.out.println("Key: " + key +" value: "+ value);
Key: 21 value: 42
If you want to iterate through data you need to define an iterator:
Iterator<Integer> Iterator = cache.keySet().iterator();
while(Iterator.hasNext()){
Integer key = Iterator.next();
System.out.println("key: " + key + " value: " + cache.get(key));
}
Sounds like HashMap<Integer,Integer> is what you're looking for.
If you are willing to use an external library, you can use apache's IntToIntMap, which is a part of Apache Lucene.
It implements a pretty efficient int to int map that uses primitives for tasks that should not suffer the boxing overhead.
If you have a limit for the size of the first list, you can just use a large array. Suppose you know there first list only has numbers 0-99, you can use int[100]. Use the first number as an array index.
Your requirements can be satisfied by the Map interface. As an example, see HashMap<K,V>.
See Map and HashMap
I am trying to create some code that will read information off of a text file. For example Bus_Routes.txtwill contain Route_A.txt 283,284 and from that the file Route_A.txt is opened and it contains 2 columns, Latitude Longitude with the coordinates listed. This I wrote out fine.
From this I am trying to get the device with id 283 to travel along the coordinates in sequence. I was recommended to use a HashMap. So my plan is to create a HashMap for the coordinates of Route_A.txt, have one column for Latitude and the other for Longitude. From that I was going to create another HashMap that will contain the device_id and the HashMap containing the coordinates, and the device_id will travel through each step of the HashMap.
Can this be done or am I completely looking in the wrong area?
If anyone has any suggestions out there, they would be much appreciated
Don't store your coordinates in a HashMap. It would be difficult to store multiple coordinates with the key (latitude?) being the same. e.g. a simple Map<Integer, Integer> would only hold one longitude value for a latitude, and that would prevent your route from having multiple destinations along the same longitude line.
I would rather use:
List<Coord>
where Coord is your lat/long pair. The List will preserve order, whereas a normal HashMap wouldn't.
Note that I'm deliberately encapsulating the lat/long pair as a specific object. You could store it as a tuple of integers but I'd rather a specific object to enforce typing, permitting addition of functionality etc. As noted elsewhere, Java is an OO language and you shouldn't shy from creating classes to represent these concepts (a sign that you should do this is when you create something like Map<String,List<Integer,Integer>>)
A HashMap is a data structure that let's you associate a value with a key, and allows, given a key, to get back the value in constant time (without the need to loop as you would have to with a list or an array, for example).
So use this structure if your usecase needs such a functionality. Having devices stored in a map, where the device ID is the key, sounds like a good idea.
If, on the other hand, you want a data structure to contain fields (like latitude, longitude), then create a class. Java is an OO language. You should create your own classes. And if you want a list of coordinates, then you should use a List<Coordinate>, and not a HashMap.
I have a HashMap of this type
Map<String, Set<String>> list_names = new HashMap<String,Set<String>>();
that I have constructed and added its elements from a txt file that has a list's name and a set of names in it.
98298XSD98 N9823923 N123781 N723872 ....
13214FS923 N9818324 N982389
... ...
I made another HashMap, called names_list that pretty much replaces the order of the list_names HashMap such that I can get all the lists that a given name is in.
now the HashMap I have is pretty big, and there are over 400k items and 60k lists.
somewhere in my code im trying to get the Set of different lists many many times and then getting the intersection of these two lists for computational purposes,
a_list = this.names_lists.get(a);
b_list = this.names_lists.get(b);
// printing lists
//intersection stuff
but whats weird is the HashMap didn't recognizance one of its keys(or maybe many of its keys) and treated it as null after one retrieval or sometimes 0 retrievals.
a:0122211029:[R3DDZP35ERRSA] b:1159829805:[R3ALX1GRMY5IMX, R1204YEYK4MBCA]
a:0122211029:[] b:1593072570:[R222JSDL42MS64]
here, im just printing the name and names_list.get(key).toString();
and yes i'm printing these before doing any intersection stuff.
any idea why is it doing that?
When you calculate the intersection of two sets, you actually modify one of the sets. You have to create a temporary set to hold the intersection, e.g.:
a_list = this.names_lists.get(a);
b_list = this.names_lists.get(b);
Set<String> intersection = new HashSet<>(a_list).retainAll(b_list);
To save time on calculations, I am making a program that will use formula to calculate a value based on the data that the user inputs. The program will prompt the user for five double values: A, B, and C, D, and E. It will then multiply A by B and then find the corresponding value on a conversion table. It will do the same for C and D and plug in the corresponding values along with E in a formula to give the user the answer. My question is: How would I include the table of values I mentioned above into my program so that I can easily find the corresponding values? I'm thinking of hardcoding these values into hashmaps but that would take quite awhile. Is there a file format that stores similar types of data that would be optimal to the situation?
Store the values in CSV. Load the values into an custom object/class with a field for each column. Start by looping over the entire set of objects to find the correct value/range each time. If that does not perform well optimize by doing things like having multiple lists of references to the objects where each list is sorted by a different column-- use those sorted lists to quickly find the correct object.
I say "range" here, because I am assuming you are sometimes looking for doubles. If the result of your calculation tells you to look for 1.999999 you may actually have to look for that +/- some tolerance. For this same reason you wouldn't want to use doubles as the keys for a map.
Currently I'm using an ArrayList to store a list of elements, whereby I will need to insert new elements at specific positions. There is a need for me to enter elements at a position larger than the current size. For e.g:
ArrayList<String> arr = new ArrayList<String>();
arr.add(3,"hi");
Now I already know there will be an OutOfBoundsException. Is there another way or another object where I can do this while still keeping the order? This is because I have methods that finds elements based on their index. For e.g.:
ArrayList<String> arr = new ArrayList<String>();
arr.add("hi");
arr.add(0,"hello");
I would expect to find "hi" at index 1 instead of index 0 now.
So in summary, short of manually inserting null into the elements in-between, is there any way to satisfy these two requirements:
Insert elements into position larger than current size
Push existing elements to the right when I insert elements in the middle of the list
I've looked at Java ArrayList add item outside current size, as well as HashMap, but HashMap doesn't satisfy my second criteria. Any help would be greatly appreciated.
P.S. Performance is not really an issue right now.
UPDATE: There have been some questions on why I have these particular requirements, it is because I'm working on operational transformation, where I'm inserting a set of operations into, say, my list (a math formula). Each operation contains a string. As I insert/delete strings into my list, I will dynamically update the unapplied operations (if necessary) through the tracking of each operation that has already been applied. My current solution now is to use a subclass of ArrayList and override some of the methods. I would certainly like to know if there is a more elegant way of doing so though.
Your requirements are contradictory:
... I will need to insert new elements at specific positions.
There is a need for me to enter elements at a position larger than the current size.
These imply that positions are stable; i.e. that an element at a given position remains at that position.
I would expect to find "hi" at index 1 instead of index 0 now.
This states that positions are not stable under some circumstances.
You really need to make up your mind which alternative you need.
If you must have stable positions, use a TreeMap or HashMap. (A TreeMap allows you to iterate the keys in order, but at the cost of more expensive insertion and lookup ... for a large collection.) If necessary, use a "position" key type that allows you to "always" generate a new key that goes between any existing pair of keys.
If you don't have to have stable positions, use an ArrayList, and deal with the case where you have to insert beyond the end position using append.
I fail to see how it is sensible for positions to be stable if you insert beyond the end, and allow instability if you insert in the middle. (Besides, the latter is going to make the former unstable eventually ...)
even you can use TreeMap for maintaining order of keys.
First and foremost, I would say use Map instead of List. I guess your problem can be solved in better way if you use Map. But in any case if you really want to do this with Arraylist
ArrayList<String> a = new ArrayList<String>(); //Create empty list
a.addAll(Arrays.asList( new String[100])); // add n number of strings, actually null . here n is 100, but you will have to decide the ideal value of this, depending upon your requirement.
a.add(7,"hello");
a.add(2,"hi");
a.add(1,"hi2");
Use Vector class to solve this issue.
Vector vector = new Vector();
vector.setSize(100);
vector.set(98, "a");
When "setSize" is set to 100 then all 100 elements gets initialized with null values.
For those who are still dealing with this, you may do it like this.
Object[] array= new Object[10];
array[0]="1";
array[3]= "3";
array[2]="2";
array[7]="7";
List<Object> list= Arrays.asList(array);
But the thing is you need to identify the total size first, this should be just a comment but I do not have much reputation to do that.