Storing multiple values for keys? - java

In Python, a dictionary can contain a key and many values for that key. I've been trying to look at Java, but there is no simple way of doing this without trying to use something like HashMap<String, List> I read that this way is very bad and it's called chaining and that it will cause a performance issue. I need to store more than hundreds of millions of keys so I need something that can scale. Each day this hash map will be emptied.
My HashMap needs to have 4 values per key like so: country, volume, network, and date. A fake example of a key looks like this: "EJTER" would it be efficient and feasible if I did something like this "EJTER_country", "EJTER_volume", "EJTER_network", "EJTER_date". These will be the keys and each respective key will have its own value. The only downside to this I see is that there will be 4x more keys than normal.

You can take a look at Guava MultiMap, it seems to be what you are looking for.

Related

Jackson JSON API: Find all occurrences of key in a string

I've used Jackson off and on for a while, so I'm familiar with it, but it has been a while and I find myself facing a little issue that I feel should be simpler than what I'm seeing, but I could be wrong.
I have a JSON string in Java. I need to find all occurrences of a particular key within that string. This key could pop up in a number of places, either in the root object, subobject, or an array of objects with who knows how much nesting. Basically, I need to find all instances of this key (along with the value), rename the key, and change the value. It's also possible that this key will not exist at all, depending on the string.
Basically, I need to find key "a", but I could have any of the following:
{b: 3, c: [{a: 0},{a: 7}]}
{a: 5, c: [], f: {a: 12}}
You get the idea. The structure has some variability to it, but in all cases I need to find all (if any) occurrences of this key and make the needed changes. Is there a simple way to do this? In a nutshell, I know that I could do something like this:
Map<String, Object> map = objectMapper.readValue(...);
And iterate through the Map, typechecking, recursing, etc as needed, but that seems to be an excessive amount of code for this. I know I could do something similar with ObjectMapper.readTree(), but then I'd be doing a pretty similar operation (typecheck, iterate, recurse), perhaps with a little less code, but still bulky. I feel like there should be a simpler way, but maybe I'm mistaken.
I am guessing that what you are looking for could be one of methods in JsonNode:
findValues()
findValuesAsText()
findParents(...)
which are all slight variations of finding values of fields with given field name; returning either List of JsonNodes (first and third), or List of Strings (second).

Get Value of HashMap using part of the key

I have an HashMap(String,Object). The key is combination of more than 1 unique ID. I have an input, a string which is part of the key(1 unique ID). I need to take the value in HashMap using that part of the key i have without iterating thousands of values in HashMap.
Can we achieve it using any Regex statement in HashMap.get()?
My Key is xxx.yyy.zzz where combination of xxx.zzz is unique throughout the Map. I have xxx and zzz as input. Also i have set of possible values of yyy(5-6 possibilities which may increase as well)for a given zzz.
I have two options to solve this now.
Map.Entry to check whether key starts and ends with xxx and zzz respectively
Trial and Error Method
i. Form key xxx.yyy.zzz with all possible yyys and check for whether the key is present or not using .contains()
ii. But this way, if i do .contains() 5-6 times for each call, won't it loop through 5-6 times at the worst case?
iii. Also i am creating more strings in stringpool.
Which one should i prefer?
The only way to retrieve a value from a HashMap without iterating over the entries/keys (which you don't want) is by searching for the full key.
If you require efficient search via a partial key, you should consider having a HashMap whose key is that partial key.
No, it's not possible to use partial keys with a HashMap.
With TreeMap this can be achieved with a partial prefix of the wanted key, as it allows you to use tailMap(String key) to return a part of the map that would follow a specific key (i.e. your keypart). You'd still need to process the entries to see which ones would match the partial key.
If your keys are like xxx.yyy.zzz and you want to use xxx.* type access then you could consider my MapFilter class.
It allows you to take a Map and filter it on a certain key prefix. This will do the searching for specific prefixes and retain the results of that search for later.
Can we achieve it using any Regex statement in HashMap.get()?
No.You can't. You need to pass the exact key to get the associated value.
Alternatively, you should itertate ober keys and get the values matched to it. They you can have regex to match your input string against key.
You cannot do this using a HashMap. However, you can use a TreeMap which will internally store the keys according to their natural order. You can write a custom search method which will find the matching key, if it exists, in the set using the regex. If written correctly, this will take O(lgN) time, which is substantially better than linear. The problem reduces to searching for a String in an ordered list of Strings.
As #Thilo pointed out, this solution assumes that you are trying to match a fragment of a key which starts at the beginning, and not anywhere else.
HashMap works on hashing algorithm that maintains hash buckets of hash code of keys and based on that hash code hash map retrieves corresponding value. For the you need to override equals() and hashcode() method for custom objects.
So
If you will try to get the value of a key, then key's hash code value get generated and further fetch operation happen based on that hash code.
If you would not give a exact match of key how HashMap will find out that bucket with a wrong hashcode ?

Java get values from LinkedHashMap with part of the key

I have the following key-value system (HashMap) , where String would be a key like this "2014/12/06".
LinkedHashMap<String, Value>
So, I can retrieve an item knowing the key, but what I'm looking for is a method to retrieve a list of the value which key matches partialy, I mean, how could I retrieve all the values of 2014?.
I would like to avoid solutions like, test every item in the list, brute-force, or similar.
thanks.
Apart from doing the brute-force solution of iterating over all the keys, I can think of two options :
Use a TreeMap, in which the keys are sorted, so you can find the first key that is >= "2014/01/01" (using map.getCeilingEntry("2014/01/01")) and go over all the keys from there.
Use a hierarchy of Maps - i.e. Map<String,Map<String,Value>>. The key in the outer Map would be the year. The key in the inner map would be the full date.
Not possible with LinkedHashMap only. If you can copy the keys to an ordered list you can perform a binary search on that and then do a LinkedHashMap.get(...) with the full key(s).
If you're only ever going to want to retrieve items using the first part of the key, then you want a TreeMap rather than a LinkedHashMap. A LinkedHashMap is sorted according to insertion order, which is no use for this, but a TreeMap is sorted according to natural ordering, or to a Comparator that you supply. This means that you can find the first entry that starts with 2014 efficiently (in log time), and then iterate through until you get to the first one that doesn't match.
If you want to be able to match on any part of the key, then you need a totally different solution, way beyond a simple Map. You'd need to look into full text searching and indexing. You could try something like Lucene.
You could refine a hash function for your values so that values with similar year would hash around similar prefixed hashes. That wouldn't be efficient (probably poor distribution of hashes) nor to the spirit of HashMaps. Use other map implementations such as TreeMaps that keep an order of your choice.

To HashMap or not to 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.

Get a value from hashtable by a part of its key

Say I have a Hashtable<String, Object> with such keys and values:
apple => 1
orange => 2
mossberg => 3
I can use the standard get method to get 1 by "apple", but what I want is getting the same value (or a list of values) by a part of the key, for example "ppl". Of course it may yield several results, in this case I want to be able to process each key-value pair. So basically similar to the LIKE '%ppl%' SQL statement, but I don't want to use a (in-memory) database just because I don't want to add unnecessary complexity. What would you recommend?
Update:
Storing data in a Hashtable isn't a requirement. I'm seeking for a kind of a general approach to solve this.
The obvious brute-force approach would be to iterate through the keys in the map and match them against the char sequence. That could be fine for a small map, but of course it does not scale.
This could be improved by using a second map to cache search results. Whenever you collect a list of keys matching a given char sequence, you can store these in the second map so that next time the lookup is fast. Of course, if the original map is changed often, it may get complicated to update the cache. As always with caches, it works best if the map is read much more often than changed.
Alternatively, if you know the possible char sequences in advance, you could pre-generate the lists of matching strings and pre-fill your cache map.
Update: Hashtable is not recommended anyway - it is synchronized, thus much slower than it should be. You are better off using HashMap if no concurrency is involved, or ConcurrentHashMap otherwise. Latter outperforms a Hashtable by far.
Apart from that, out of the top of my head I can't think of a better collection to this task than maps. Of course, you may experiment with different map implementations, to find the one which suits best your specific circumstances and usage patterns. In general, it would thus be
Map<String, Object> fruits;
Map<String, List<String>> matchingKeys;
Not without iterating through explicitly. Hashtable is designed to go (exact) key->value in O(1), nothing more, nothing less. If you will be doing query operations with large amounts of data, I recommend you do consider a database. You can use an embedded system like SQLite (see SQLiteJDBC) so no separate process or installation is required. You then have the option of database indexes.
I know of no standard Java collection that can do this type of operation efficiently.
Sounds like you need a trie with references to your data. A trie stores strings and lets you search for strings by prefix. I don't know the Java standard library too well and I have no idea whether it provides an implementation, but one is available here:
http://www.cs.duke.edu/~ola/courses/cps108/fall96/joggle/trie/Trie.java
Unfortunately, a trie only lets you search by prefixes. You can work around this by storing every possible suffix of each of your keys:
For 'apple', you'd store the strings
'apple'
'pple'
'ple'
'le'
'e'
Which would allow you to search for every prefix of every suffix of your keys.
Admittedly, this is the kind of "solution" that would prompt me to continue looking for other options.
first of all, use hashmap, not hashtable.
Then, you can filter the map using a predicate by using utilities in google guava
public Collection<Object> getValues(){
Map<String,Object> filtered = Maps.filterKeys(map,new Predicate<String>(){
//predicate methods
});
return filtered.values();
}
Can't be done in a single operation
You may want to try to iterate the keys and use the ones that contain your desired string.
The only solution I can see (I'm not Java expert) is to iterate over the keys and check for matching against a regular expression. If it matches, you put the matched key-value pair in the hashtable that will be returned.
If you can somehow reduce the problem to searching by prefix, you might find a NavigableMap helpful.
it will be interesting to you to look throw these question: Fuzzy string search library in Java
Also take a look on Lucene (answer number two)

Categories