Distribute values from a map to an array in a balanced way - java

I am trying to get a balancing algorithm but struggling to understand how to acheieve this.
I have a HashMap as below:
Map criteria = new HashMap();
criteria.put("0",5);
criteria.put("1",8);
criteria.put("2",0);
criteria.put("3",7);
...
Also, I have a two-dimensional array where I need to have the values fetched from the HashMap and put into the array in a balanced way.
String[][] arr = new String[3][1];
The end result I am looking for is something like this:
arr[0][0]="0"; (the key of the hashmap)
arr[1][0]="1";
arr[2][0]="2,3"; (as the key "2" has the value less among the first two entries, the key "3" should be appended top this node)
So, basically the keys of the HashMap should get evenly distributed into the Array based on its values.
Thanks a lot in advance for the help.

Related

Java three attributes, best way to store + sort

I have a datastructure stored in a map with a multimap as values that I want to sort by multiple attributes.
Background: I have a JavaFX GridPane in which I want to display some things in an ordered form. So for each point within the GridPane I have some Elements with one+ String related to them. I want to display the Elements based on the alphabetical order of the Strings.
I have the following for now:
Map<Coordinate, Multimap<Element, String>> myMap = new HashMap<Coordinate, Multimap<Element, String>>();
But for me it is not clear, how to do the sorting. As you see by the usage of Multimap, one Element can have multiple Strings. At the end I want to order by Coordinate (x and y) and by the String attribute for each coordinate. How to do that? Or does anyone have a better idea how to store these attributes?
Edit: Coordinate sorting is easy and not the problem:
List<Coordinate> keys = new ArrayList<Coordinate>(myMap.keySet());
Comparator<Coordinate> comparator = Comparator.comparing(Coordinate::getX).thenComparing(Coordinate::getY);
Collections.sort(keys, comparator);
I have just explained it to make my problem clear. The main problem is: How to sort the strings with related elements for each coordinate. Or a "better" structure to save the attributes.
Thanks!
Oh damn. Can answer this question by myself. I just make the String the key and the Element the value. Then using
ListMultimap<String, Element> lmm = Multimaps.newListMultimap(
new TreeMap<>(), ArrayList::new);
as suggested here. Et voilĂ ... For each Coordinate the inner map is sorted by the String attribute.

How to get most recent 100 data from a Map?

I have a Map of Long and String - Map which stores my timestamp as the key and value as my data.
Map<Long, String> eventTimestampHolder = new HashMap<Long, String>();
Now I want to get 100 most recent data from the above map by looking at timestamp which is part of key and then keep on adding those data in a List of String. In general populate the 100 most recent data in a List.
What is the best way to do this? Can I use TreeMap here and it will sort my keys basis on the timestamp properly?
In general my timestamp is going to look like this - 1417686422238 and it will be in milliseconds
In case you mean by "recent" recently added, then you can try LinkedHashMap which will maintain the order of insertion. Then you can iterate over the first 100 items.
You can iterate over the map like this:
for(Long key : eventTimestampHolder.keySet()) {
String value = eventTimestampHolder.get(key);
}
For any key that can be sorted, you should use a SortedMap (unless there are other requirements making it unsuitable). A TreeMap is a sorted map. Since you need the most recent k entries, you need the largest keys first. This can be done by going through the k first keys in the map's descendingKeySet as follows, a one-liner in Java-8:
eventTimestampHolder.descendingKeySet().stream().limit(k); // in your case, k = 100
If you want not just the keys, but the values as well, then you could find the k'th key, and then use
// the 2nd arg is a boolean indicating whether the k'th entry will be included or not
eventTimestampHolder.tailMap(kthTimestamp, true);
One thing to remember when using tailMap is that it will be backed by the original eventTimestampHolder map, and any changes to that will be reflected in the returned tail map.

convert multi key list into multidimensional sorted map

I am using multi key bags in order to count occurrences of certain combinations of values and I was wondering if there is an elegant way to convert these bags into nested SortedMaps like TreeMaps. The number of nested TreeMaps being equal to the number of components in the multi key. For instance, let's say I have a multi key bag which has a defined key:
multiKey = new String[]{"age", "height", "gender"}
thus, the object I would like to obtain from it would be:
TreeMap<Integer, TreeMap<Integer, TreeMap<Integer, Integer>>>
and populate it with the values from the multi key bag. So, the nested structure would contain the values from the multi key like this:
TreeMap<"age", TreeMap<"height", TreeMap<"gender", count>>>
where "age" is replaced by the corresponding value from the bag, "height" as well and so on.. count is the number of occurrences of that particular combination (which is returned by the multi key bag itself).
Of course, the number of components of the multi key is dynamic.
If the multiKey would have only two components, then the resulting object would be:
TreeMap<Integer<TreeMap<Integer, Integer>>
Retrieving the values from the bag and populating the (nested) TreeMaps does not represent an issue. Only the conversion. Any help is appreciated.
Instead of using a bunch of wrappers, why don't you just create your own class that groups related data together? It seems like this would very much simplify the process.
Nonetheless, If what you actually want is to be able to perform complex queries on your data (pseudo-code):
SELECT ALL (MALES >= 25 && HEIGHT < 6'1) && (FEMALES < 40 && HEIGHT > 5'0)
Then you should probably look into using a database. I'm not saying that a Tree is bad, but if your goal is to be able to easily/quickly perform complex queries, then a database is the way to go. Of course, you could write your own classes/methods to perform these calculations for you, but why reinvent the wheel if you don't have to?

Why doesn't my HashTable allow key collisions?

I read that HashTable can map same key to multiple values. That's what collision is.
Now I run the program like this:
Dictionary<String,String> hTable = new Hashtable<String,String>();
hTable.put("a", "aa");
hTable.put("a", "ab");
System.out.println(""+hTable.get("a"));
My thinking says I should get aa and ab.
But actual output is ab
Why is it so? Where is the collision then?
There is no collision. A HashTable entry maps a key to only one value.
The third line in your sample:
hTable.put("a", "ab");
replaces the mapping from a to aa with a mapping from a to ab.
After your four lines of code complete execution, hTable has only one mapping: a to ab.
A collision only happens internally. To the user, are resolved transparently.
That's why a hashtable can be a dictionary -- it maps each key to exactly 1 value. If it mapped to more than 1 value then it wouldn't be a dictionary.
Hashtable doesn't map the same key to multiple values. Collision is that multiple keys might be mapped to the same hash value. It is resolved by the data structure itself which is transparent to you.
If you want to get aa and ab by hTable.get("a"), you need to create Dictionary<String,List<String>> and append the list with the values of the same key.
In your code
hTable.put("a", "aa");
hTable.put("a", "ab");
The keys are the same. So the second operation used "ab" to override "aa". That's why you only get "ab".
HashTable is Key -> Value mapping. That means you can not have multiple values for more one key. You need to combine two data structures store multiple values with one key.
For Example,
You can put a linkList inside you HashTable. For example
HashTable<String,LinkedList<String>> table = new HashTable();
LinkedList<String> list = new LinkedList();
list.add("aa");
list.add("ab");
table.add("a",list);
now you can do this get aa and ab value;
table.get("a").get(0); // returns aa
table.get("a").get(1); // returns ab
I strongly recommend you to go through the basics of data structure and algorithm.
You want to retrieve values by their keys. An array serves this purpose but is restricted to using integer keys and may use too much space (think about storing values at position 0 and 1000 only, you have to allocate the entire array for 2 elements).
HashTables solve both of these problems with:
a dispersive non-injective function that converts an array of bytes of variable length in a fixed length array of bytes. This means that you have hash(bytes_1) == hash(bytes_2) but it doesn't happen too often and if bytes_1 ~ bytes_2 the hashes are different;
an index of used hashes. If the function returns an array of 10 bytes you have 2^80 possibilities, so you need to keep a sorted list of the hashes that you already encountered;
an array of linked lists. The index of hashes maps the hash with the position in the array.
The collision means that two keys have the same hash: map.put("key1", "value1"); map.put("key2", "value2") key1 and key2 might wind up in the same linked list.

nth item of hashmap

HashMap selections = new HashMap<Integer, Float>();
How can i get the Integer key of the 3rd smaller value of Float in all HashMap?
Edit
im using the HashMap for this
for (InflatedRunner runner : prices.getRunners()) {
for (InflatedMarketPrices.InflatedPrice price : runner.getLayPrices()) {
if (price.getDepth() == 1) {
selections.put(new Integer(runner.getSelectionId()), new Float(price.getPrice()));
}
}
}
i need the runner of the 3rd smaller price with depth 1
maybe i should implement this in another way?
Michael Mrozek nails it with his question if you're using HashMap right: this is highly atypical scenario for HashMap. That said, you can do something like this:
get the Set<Map.Entry<K,V>> from the HashMap<K,V>.entrySet().
addAll to List<Map.Entry<K,V>>
Collections.sort the list with a custom Comparator<Map.Entry<K,V>> that sorts based on V.
If you just need the 3rd Map.Entry<K,V> only, then a O(N) selection algorithm may suffice.
//after edit
It looks like selection should really be a SortedMap<Float, InflatedRunner>. You should look at java.util.TreeMap.
Here's an example of how TreeMap can be used to get the 3rd lowest key:
TreeMap<Integer,String> map = new TreeMap<Integer,String>();
map.put(33, "Three");
map.put(44, "Four");
map.put(11, "One");
map.put(22, "Two");
int thirdKey = map.higherKey(map.higherKey(map.firstKey()));
System.out.println(thirdKey); // prints "33"
Also note how I take advantage of Java's auto-boxing/unboxing feature between int and Integer. I noticed that you used new Integer and new Float in your original code; this is unnecessary.
//another edit
It should be noted that if you have multiple InflatedRunner with the same price, only one will be kept. If this is a problem, and you want to keep all runners, then you can do one of a few things:
If you really need a multi-map (one key can map to multiple values), then you can:
have TreeMap<Float,Set<InflatedRunner>>
Use MultiMap from Google Collections
If you don't need the map functionality, then just have a List<RunnerPricePair> (sorry, I'm not familiar with the domain to name it appropriately), where RunnerPricePair implements Comparable<RunnerPricePair> that compares on prices. You can just add all the pairs to the list, then either:
Collections.sort the list and get the 3rd pair
Use O(N) selection algorithm
Are you sure you're using hashmaps right? They're used to quickly lookup a value given a key; it's highly unusual to sort the values and then try to find a corresponding key. If anything, you should be mapping the float to the int, so you could at least sort the float keys and get the integer value of the third smallest that way
You have to do it in steps:
Get the Collection<V> of values from the Map
Sort the values
Choose the index of the nth smallest
Think about how you want to handle ties.
You could do it with the google collections BiMap, assuming that the Floats are unique.
If you regularly need to get the key of the nth item, consider:
using a TreeMap, which efficiently keeps keys in sorted order
then using a double map (i.e. one TreeMap mapping integer > float, the other mapping float > integer)
You have to weigh up the inelegance and potential risk of bugs from needing to maintain two maps with the scalability benefit of having a structure that efficiently keeps the keys in order.
You may need to think about two keys mapping to the same float...
P.S. Forgot to mention: if this is an occasional function, and you just need to find the nth largest item of a large number of items, you could consider implementing a selection algorithm (effectively, you do a sort, but don't actually bother sorting subparts of the list that you realise you don't need to sort because their order makes no difference to the position of the item you're looking for).

Categories

Resources