Java get values from LinkedHashMap with part of the key - java

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.

Related

Self-Sorted Data Structure with Key Lookup/Merge

I am looking for a value-sorted data structure in Java that supports key lookup/merging(Note: the key and the value are seperated properties)
My past experiences were:
TreeMap with a custom CompareByValueComparator, which yielded a bugged map that did not match the keys correctly and I could never figure out why.
TreeSet with Map.Entry elements, which does not support keys searching and I have to search element by element to find that key, which takes O(n) time and is not really efficient.
HashMap and TreeSet combination, which is very slow when transfering elements from one structure to the other, or bulky if you want to maintain both.
Thanks
EDIT1: fix the wording about "casting" in the third options.

Questions about Java's library map classes?

The answers are (2) and (4) but not sure why. I don't have much foundation on these topics. Could someone please explain why these are the correct answers and why the others are incorrect.
Thank you
A HashMap is a data structure that consists of keys and values. Values are stored in the HashMap with an associated key. The values can then be retrieved by recalling from the HashMap with the same key you used when putting the value in.
1
TreeMaps and LinkedHashMaps are different versions of a Map. A HashMap uses hashing to store its keys, whereas a TreeMap uses a binary search tree to store its keys and a LinkedHashMap uses a LinkedList to store keys. If you iterate over a HashMap, the keys will be returned in hash-sorted order (unpredictable in most cases), because that's how they were stored. The TreeMap, however, has a tree of all the values, so when you iterate over the tree, you'll get all the keys in actual sorted order. A LinkedHashMap has the keys in an ordered list, so an iterator will return the keys in the same order in which you inserted them.
2, 3, and 5
In a HashMap, values are looked up using their keys. If you had duplicate keys, the HashMap couldn't know which value to return. Therefore, every key in a HashMap must be unique, but the values do not have to be.
4
In a normal HashMap, the key is hashed and then inserted in the appropriate spot. With a TreeMap and a LinkedHashMap, you have the additional overhead of inserting the key into the tree or linked list which will take up additional time and memory.

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 ?

What is LinkedHashMap and what is it used for?

When I was going through a example code which has ListViews I came up with LinkedHashMap.
What is a LinkedHashMap and where can we use it and how? I went through several articles but did not understand fully. Is it necessary when creating ListView. What is the connection between ListViews and LinkedHashMaps? Thank you.
For Simplicity, let us understand what is the difference between HashMap and LinkedHashMap.
HashMap: It gives output in Random orders means there is no proper sequence how we have inserted values.
whereas
LinkedHashMap: It gives output in sequential order.
Let us see a small example: with HashMap
// suppose we have written a program
.
.
// now use HashMap
HashMap map = new HashMap(); // create object
map.put(1,"Rohit"); // insert values
map.put(2,"Rahul");
map.put(3,"Ajay");
System.out.println("MAP=" +map); //print the output using concatenation
//So the output may be in any order like we can say the output may be as:
Map={3=Ajay,2=Rahul,1=Rohit}
but this is not the case in LinkedHashMap
Just replace the "HashMap" with "LinkedHashMap" in the above code
and see
it will display the output in Sequential order like 1=Rohit will be displayed first then the others in sequence.
The docs are here. But its basically a HashMap that also has a linked list, so you can have a consistently ordered iteration through it. Note that this means removals may be O(n) time because you need to remove it from both data structures.
LinkedHashMap is hashmap. But it maintains order of insertion. But HashMap doesnt maintain order.
Hi Linked Hash Map is a Map which stored key value pair,
Linked Hash Map add the values may very slow, But while retrieving the values is very easy.
For fast retrieval of values we could prefer Linked Hash Map.

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