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.
Related
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.
Below is a piece of code which I use for inserting the values in a hashmap.
String[] folders={"Movies/HD/By Genre/Action","Movies/HD/By Genre/Comedy"};
HashMap<String, String> sdsResults = new HashMap<String, String>();
for(int i=0; i<folders.length; i++){
sdsResults.put(folders[i], null);
}
Iterator<String> itr = sdsResults.keySet().iterator();
while(itr.hasNext()){
System.out.println("keys in map are = "+itr.next());
}
The output is -
keys in map are = Movies/HD/By Genre/Comedy
keys in map are = Movies/HD/By Genre/Action
Now I wanted to keys to come in the same order as how I had put in. i.e. first the Action one should come and then the Comedy. But reverse order is coming.
Can someone explain why is it so? And I want the order to be the same as the folder contents. How can I achieve this?
The order of keys in a hash is not defined. You want a map. Here's a comparison of the internals.
Basically, when you put something in a hash, you scramble the key. This is a one-way function. The whole point is that you can't un-do it -- it's a way of putting 100 things in 10 boxes.
LinkedHashMap should solve the problem of ordering.
Similar question and the answer here Order of values retrieved from a HashMap
You can use ListOrderedMap from Apache's Commons-Collection library to keep the order.
I have four lists of recommendations and lets say the lists are A,B,C,D.
Every list has the same number of items and are represented as key-value pairs. But I need to give more priority(weights) for the elements of list A than list B, so on. Ultimately I need to select the best set of items from the four lists for the final recommendation.
Here is a use case:
List_A:
{item1,weight1}
{item2,weight1}
{item3,weight1}
{item4,weight1}
{item5,weight1}
List_B:
{item8,weight2}
{item5,weight2}
{item7,weight2}
{item2,weight2}
{item6,weight2}
List_C:
{item11,weight3}
{item23,weight3}
{item34,weight3}
{item24,weight3}
{item5,weight3}
List_D:
{item9,weight4
{item7,weight4
{item3,weight4
{item2,weight4
{item5,weight4
Suppose weight1=10, weight2=5, weight3=3, weight1=2
According to these lists the final list should have "item5" as the first item, because it exists in all four lists. How can I get the other best recommendations for these four lists?
Thanks.
If I understand you right, this should be a bit simple. On a higher level you need a data structure as
Map<Item, Map<List, Integer>> where the final integer is number_of_occurrences. Once you have it is straightforward to multiply number_of_occurrences * weight and throw it along with generated value in a TreeMap (a priority queue can also be used here)
Now you can have the top-n list from the TreeMap.
How to sort (any kind of sorting) a key of a map(treemap or hashmap)
i have a problem and it goes like this.
i have a map that has a key of
27527-683,
27525-1179,
27525-1571,
27525-1813,
27525-4911,
27526-1303,
27526-3641,
27525-3989,
27525-4083,
27525-4670,
27526-4102,
27526-558,
27527-2411,
27527-4342
this is the list of keys and the value for each of the key is a list.
now, how can i sort this key in ascending order by number.
ex. if i want to sort : 1,2,11,20,31,3,10
i want to have as output is : 1,2,3,10,11,20,31
but when i use the autosort of treemap the output goes : 1,10,11,2,20,3,31
how can i sort it in ascending order by numeric?
please help me. i can't think of anymore ways because this is my first time handling map and list
Your keys are Strings. The natural ordering of strings is lexicographical. You either need to specify a custom comparator in the constructor of the TreeMap, or use an Integer key.
Furthermore, you can better represent a Map<Key, List<Value>> as a Google Guava Multimap, see for example SortedSetMultimap.
Continuing with the Guava example:
Multimap<Integer, Person> multimap = SortedSetMultimap.create(Ordering.natural(), Ordering.arbitrary());
multimap.put(1, x);
multimap.put(1, y);
multimap.put(2, z);
multimap.put(1, a);
Then
multimap.get(1) will return a set containing [x, y, a] in some arbitrary order.
multimap.keys() will return a sorted set of [1, 2].
Your keys are currently Strings, that you would appear to rather handle like Integers. You will need to reformulate how you handle the map object, as many people here have suggested (it may be the correct method). An easier method involves using that list of keys you have copied us in on.
I see there is a way to output the list of keys. Sort that however you like. Arrays and lists are easily sorted by built in commands from your runtime environment. You might have to first split those elements at the hyphen.
I'd recommend a book on Data Structures.
Use SortedMap, for example, java.util.TreeMap.
keyword : SortedMap
SortedMap<Integer, Integer> s = new TreeMap<Integer, Integer>();
s.put(1, 1);
s.put(4, 2);
s.put(2, 3);
System.out.println(s); //{1=1, 2=3, 4=2}
also look at this example
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).