I'm having trouble picking between an array, arraylist, or a list for one of the features of this small game I'm designing in Java. I'm not limited to those three, those are just the ones I know of.
The feature is that the player unlocks a certain text/button whenever they reach that certain amount of points. So, what I would like to store a "list" that contains a collection of two points. One point that gives the required point amount, and the second point is either a string or something else that would be unlocked.
I was leaning towards just a plain old 2-d array for this but decided to post it here so I could get more opinions.
If the two values are linked I would use a HashMap to store the values. This allows you to easily access the corresponding value. Example: (Assuming the points that are linked to the achievement are int's and the achievement is a String)
HashMap<Integer, String> hashmap = new HashMap<>();
assignments.put(18, "New Achievement");
//Etc
Where 18 is the number of points and New Achievement is the achievement the user has unlocked.
As chrylis said if the values are in continuous order a NavigableMapwould be a good choice to look into.
A good tutorial for the NavigableMap
Related
I have an assignment on Data structure, the prof wants us to use different kinds of DS in the project, but I don't know what he means with (A three-dimensional data structure that holds items in a positional relationship to each other. Each cell in the data structure can hold multiple items.)
I tried Arraylists of objects, queues with objects!
any idea what kind of DS I can try to save my time?
thanks
If you are allowed to use Guava, then I would consider a Multimap of MyObj indexed by XyzCoord, where XyzCoord is a custom object to hold three positional numbers, and MyObj is the custom object you wish to store one or more of at various coordinates.
Avoiding Guava, you can use a standard Map of List<MyObj>. It could also be indexed by List<Integer> which are of length 3.
The fact is that there are many, many ways to do this. Your question may be a bit too broad as a result. Have a look at the collection classes some more and try to ask specific questions about each one if you don't know how they are used.
The simplest spatial data structure is a 3D array. In java you can create one with as follows:
Object[][][] my3DArray = new Object[10][10][10];
Here you can store 10*10*10=1000 Object in spatial relation to each other. Unfortunately, there are only 10 possible coordinates in each dimension.
If you want something more efficient, look for quadtrees/octrees, kd-trees (as mentioned by #BeyelerStudios in the comments), R-Trees, LSH (locality sensitive hashing) or even space-filling curves (Z-curve, Hilbert curve, ...). These are just the main families, there are many versions of DSs of each type.
EDIT to answer comment.
Except the 3D array approach, all solutions above are quite space efficient. The most space efficient one may be the PH-Tree (a type of quadtree, developed by myself) in some cases it may require less memory than a plain array of coordinates. Unfortunately it is comparatively complex to understand and implement.
If you want to use a 1D sorting scheme, such as array or list, try using a space filling curve. The Z-curve may be easiest.
Using spacefilling curves you can calculate a 'key' (z-key or Morton-number) for each point in space and then sort these in the array or list. In such an ordered list/array, direct neighbors are also likely (but not guaranteed) to be close in 3D space. Inversely, points that are close in 3D space tend (but not guaranteed) to be close in the list/array.
For integer coordinates, the z-key (also called MortonNumber) can be calculated by interleaving the bits of the coordinates. You can also do this for floating points values, but you need to be careful with negative values, otherwise you may get a rift between positive and negative values.
The issue I am having is showing up every now and then, and it's quite annoying.
I have two arraylists:
* One keeping track of names
* One keeping track of "counters" of how many times these names are used
The problem:
The counters "connected" to each name can be different. I want to select the 6 names with the lowest counters connected to them. How do i do this, while keeping the selection random if there are 7 or more names with the lowest counters connected to them?
For info:
The two arraylists are "connected" by being shuffled with the same random seed.
The reason they are shuffled at random is because for the first draw (5 draws - 1 for each day) everyone starts at count 0. By shuffling the arraylists I can make sure the selection is randomized.
I hope this makes sense to you. If my description is poorly worded or you have issues understanding something, ask away :)
Simply don't use multiple arrays, use a class like CountedName which stores the name and the counter. Then you can simply sort the array of those countedNames by using a custom comparator which orders based on the stored count.
Rather than creating two separate arrays/list, you can maintain one hashmap storing names as key and counts as values and you can provide your customised logic to increment/decrements counters accordingly.
You could create an object (a class) that contains the name and the counter as variables. You'll then store these object in one single array your can shuffle as you want.
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 an assignment that I am working on, and I can't get a hold of the professor to get clarity on something. The idea is that we are writing an anagram solver, using a given set of words, that we store in 3 different dictionary classes: Linear, Binary, and Hash.
So we read in the words from a textfile, and for the first 2 dictionary objects(linear and binary), we store the words as an ArrayList...easy enough.
But for the HashDictionary, he want's us to store the words in a HashTable. I'm just not sure what the values are going to be for the HashTable, or why you would do that. The instructions say we store the words in a Hashtable for quick retrieval, but I just don't get what the point of that is. Makes sense to store words in an arraylist, but I'm just not sure of how key/value pairing helps with a dictionary.
Maybe i'm not giving enough details, but I figured maybe someone would have seen something like this and its obvious to them.
Each of our classes has a contains method, that returns a boolean representing whether or not a word passed in is in the dictionary, so the linear does a linear search of the arraylist, the binary does a binary search of the arraylist, and I'm not sure about the hash....
The difference is speed. Both methods work, but the hash table is fast.
When you use an ArrayList, or any sort of List, to find an element, you must inspect each list item, one by one, until you find the desired word. If the word isn't there, you've looped through the entire list.
When you use a HashTable, you perform some "magic" on the word you are looking up known as calculating the word's hash. Using that hash value, instead of looping through a list of values, you can immediately deduce where to find your word - or, if your word doesn't exist in the hash, that your word isn't there.
I've oversimplified here, but that's the general idea. You can find another question here with a variety of explanations on how a hash table works.
Here is a small code snippet utilizing a HashMap.
// We will map our words to their definitions; word is the key, definition is the value
Map<String, String> dictionary = new HashMap<String, String>();
map.put("hello","A common salutation");
map.put("chicken","A delightful vessel for protein");
// Later ...
map.get("chicken"); // Returns "A delightful vessel for protein";
The problem you describe asks that you use a HashMap as the basis for a dictionary that fulfills three requirements:
Adding a word to the dictionary
Removing a word from the dictionary
Checking if a word is in the dictionary
It seems counter-intuitive to use a map, which stores a key and a value, since all you really want to is store just a key (or just a value). However, as I described above, a HashMap makes it extremely quick to find the value associated with a key. Similarly, it makes it extremely quick to see if the HashMap knows about a key at all. We can leverage this quality by storing each of the dictionary words as a key in the HashMap, and associating it with a garbage value (since we don't care about it), such as null.
You can see how to fulfill the three requirements, as follows.
Map<String, Object> map = new HashMap<String, Object>();
// Add a word
map.put('word', null);
// Remove a word
map.remove('word');
// Check for the presence of a word
map.containsKey('word');
I don't want to overload you with information, but the requirements we have here align with a data structure known as a Set. In Java, a commonly used Set is the HashSet, which is almost exactly what you are implementing with this bit of your homework assignment. (In fact, if this weren't a homework assignment explicitly instructing you to use a HashMap, I'd recommend you instead use a HashSet.)
Arrays are hard to find stuff in. If I gave you array[0] = "cat"; array[1] = "dog"; array[2] = "pikachu";, you'd have to check each element just to know if jigglypuff is a word. If I gave you hash["cat"] = 1; hash["dog"] = 1; hash["pikachu"] = 1;", instant to do this in, you just look it up directly. The value 1 doesn't matter in this particular case although you can put useful information there, such as how many times youv'e looked up a word, or maybe 1 will mean real word and 2 will mean name of a Pokemon, or for a real dictionary it could contain a sentence-long definition. Less relevant.
It sounds like you don't really understand hash tables then. Even Wikipedia has a good explanation of this data structure.
Your hash table is just going to be a large array of strings (initially all empty). You compute a hash value using the characters in your word, and then insert the word at that position in the table.
There are issues when the hash value for two words is the same. And there are a few solutions. One is to store a list at each array position and just shove the word onto that list. Another is to step through the table by a known amount until you find a free position. Another is to compute a secondary hash using a different algorithm.
The point of this is that hash lookup is fast. It's very quick to compute a hash value, and then all you have to do is check that the word at that array position exists (and matches the search word). You follow the same rules for hash value collisions (in this case, mismatches) that you used for the insertion.
You want your table size to be a prime number that is larger than the number of elements you intend to store. You also need a hash function that diverges quickly so that your data is more likely to be dispersed widely through your hash table (rather than being clustered heavily in one region).
Hope this is a help and points you in the right direction.
In a game, I'm trying to keep a list of users and have it sorted by score, so that I could query the list at any given time and return (for example) the top ten users by score. This list should be thread-safe. I envision using the userName string as a key and the value would be a User object which implements Comparable and has properties such as displayName and score. The User object would therefore have a compareTo method which would compare the score attribute to determine its position.
I'm looking at using a ConcurrentSkipListMap for this, but as best I can tell, the Map (as opposed to the Set) uses the key to sort. I'd like to have the list sorted by the score property of the User object, but still use a Map because I need to be able access any given user and modify their score attribute from a thread.
It doesn't seem that using my own Comparator for the key would solve my problem, as I doubt I'd have access to the associated value for comparison. I could use a ConcurrentSkipListSet but accessing the list to modify an individual user's score would be (I would imagine) an expensive operation (due to the need to iterate every time).
Would anyone be able to suggest how to accomplish this?
No, I don't think you can. The comparator used for ordering is the same one used for indexing. You will probably have to maintain 2 collections. One for keeping the ordering of user's scores the for referring to the users by name.
get(key) depends on the comparator (to be able to locate the key). You propose a comparator that would depend on get(key) (to access the mapped value of a key an compare based on that). That necessarily leads to infinite recursion and stack overflow (on the bright side, you are posting at the right website!!)
Michael is right, you can't have your cake and eat it too ;)
I think you have 3 choices:
Use a Map so that updates to a user's score are quick, and you pay the price when sorting to find the highest scores.
Use a SortedSet that sorts by score so that finding the highest scores is fast, but you must pay the price when updating user's scores
Maintain two data structures, so that you can have the best of 1 and 2. For example, you have your real data in a set sorted by score, but then also maintain a mapping of username to index into the set or similar. That way you always have the sorted scores, and updating a user's score is just a lookup, not a search. The price you pay for this is now you are maintaining some duplicate information in two places, and especially considering concurrent access, it can be tricky ensuring both places are always updated in synch.
I would not make assumptions about which is faster between 1 & 2. I would try them both out with your expected usage and measure to see what is worst.
If you are really only interested in the top n scores, then there is the possibility to just maintain that list separately. So have your map of username to score for everyone, but also maintain a small set of the top scores (and their users). Every time you add/update someone's score, just check the score against the top score list, and if it's bigger than the smallest one there, just add it and bump off the lower one. This is similar to suggestion 3 above, but is less overhead and perhaps easier to maintain.