Put keys in hashmap and retrieve in same order - java

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.

Related

Is there a way to map a set to a string without creating many set instances?

I have a school project that involves recommending a university course to students to study based on four favorite subjects each user enters.
My approach is to use HashMap in Java: HashMap<String, Set<String>>. The course is the simple string, while each set contains the four subjects required for the course.
Each entry should be added manually but in turn it requires many instances of the Set objects for each entry:
Set<String> setA = new HashSet<String>(); // for first pair
Set<String> setB = new HashSet<String>(); // for second pair.
And so on...
For each key/value entry, I want to check/compare the value (set of subjects) with the four subjects entered by the user and if the set contains the entered subjects, the key (course) is added to a matches array.
Does anyone have any idea on how I should go about this?
I have tried working on this. I really need to meet the deadline
What I'm assuming you want is a Map.Entry. You mentioned in your question you want to use a HashMap. To loop through a HashMap's list of values you would do something like this:
for(Map.Entry<Integer, Integer> eachEntry : hashMap.entrySet())
{
int key = eachEntry.getKey();
int value = eachEntry.getValue();
}
In my example it's a hashmap containing Integer key value pairs, but you can change it to the type you want. A quick google search would show how to go through a Set inside of a hashmap. Hope this helps
You can compare values this way , by iterating through the hashMap keys
for(String course: hashMap.keySet()) {
//Convert all the set values to lower case. Also do the same for user entered subjects set.
Set<String> newSet = hashMap.get(course).stream().map(String::toLowerCase).collect(Collectors.toCollection(HashSet::new));
if( newSet.containsAll(userEnteredCourses)) {
matchesArray.add(course);
}
}

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 sum up values in a HashMap<String, <String,Integer>>?

I have a following HashMap:
HashMap<String, HashMap<String,Integer>> dataArray = new HashMap<>();
In the program, I do use enhanced loop to iterate few times and insert data into the HashMap, based on some kind of key, as in:
dataArray.get(primaryKey).put(length, totalCost)
It produces the following output:
{123-456-789={00:05:00=500, 00:01:06=220}, 999-090-090={00:08:01=900}}
I use a formula to calculate the totalCost value, but I have to make sure it is set to 0 at each iteration's beginning.
My question is, I want to sum up totalCost and length values for each primaryKey. The end result should be something like this:
{123-456-789={00:06:06=720}, 999-090-090={00:08:01=900}}
How would I accomplish that? Do I have to create another HashMap, or is it possible to modify the ones already existing? With a loop perhaps?
EDIT: Forgot to mention that if I try to obtain existing totalCost value with dataArray.get(primaryKey).get(totalCost), compiler complains about a suspicious call to java.util.Map and returns null.
Why so complicated? Just alter your data-structure. OOP is meant to solve precisely that problem. Just store the subtables in an Object each and provide appropriate methods/variables. As for inserting the data into the existing Map: How would you distinguish the resulting sums from what you inserted as standard-values? In addition this would quite likely cause a concurrent modification, though there are ways to work around that.
If you want a an end result in following form :
{123-456-789={00:06:06=720}, 999-090-090={00:08:01=900}}
Why not change your loop to something like this by maintaining only one key-value pair in the map:
Map.Entry<String,Integer> entry=dataArray.get(primaryKey).entrySet().iterator().next();
String key= entry.getKey();
dataArray.get(primaryKey).put(key + length, dataArray.get(primaryKey).get(key) + totalCost);
I hope this helps!

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.

are there an efficent way to sort a parametermap?

I have a parameter map incoming from a post in a web form. The problem I have is that I want to have the key values sorted.
I have two keys incoming j_idt40:j_idt41:0:score and j_idt40:j_idt41:0:scoreID These I would either want to find without resorting to loop through the map for every row I iterate again. Is there a better way to do this?
j_idt40:j_idt69 = Uppdatera
j_idt40:j_idt41:3:score = 200
j_idt40:j_idt41:0:scoreID = 1
j_idt40:j_idt41:4:scoreID =
j_idt40:j_idt41:3:scoreID = 4
j_idt40:j_idt41:2:scoreID = 3
j_idt40:j_idt41:0:score = 203
j_idt40:j_idt41:2:score = 200
j_idt40:j_idt41:1:score = 200
j_idt40 = j_idt40
j_idt40:j_idt41:4:score = 800
j_idt40:j_idt41:1:scoreID = 2
Natural sorting you need to write your own comparator. The existing comparators in jdk will fail on the following scenario.
TreeMap<String,String> treeMap = new TreeMap<String, String>();
treeMap.put("key1", "value");
treeMap.put("key2", "value");
treeMap.put("key20", "value");
treeMap.put("key10", "value");
treeMap.put("key11", "value");
treeMap.put("key21", "value");
The sorting will happen like this.
key1,key10,key11,key2,key20,key21
Natural sorting is implemented in Java 8 see here
or
Use apache commons ComparatorUtils.NATURAL_COMPARATOR
will TreeMap help you in this regard ?
TreeMap Keeps everything sorted. This is built-in class in Java collection API.
You can use this constructor to convert your map to sorted map.
TreeMap(Map m) // this is from 'java.util.TreeMap'
You can pull all the Map.Entries out into a list, sort that, then loop through it once. You've have to make a Comparitor for Map.Entries.
You can sort the keys like this:
Collection<?> keys = params.keySet();
String[] array = keys.toArray(new String[keys.size()]);
Arrays.sort(array);
Or if you want the entries of the map to be ordered, you can achieve this by inserting them into a TreeMap. When you iterate the TreeMap's key set they come out in order.
Which approach is more "efficient" depends on what measure of efficiency you are talking about (CPU, memory, developer time).
It also depends on how often various things are performed by your application. For example:
lookup, insert and delete operations are on average O(1) for a HashMap and O(logN) for a TreeMap
iterating a TreeMap's key set is O(N)
extracting and sorting a Hashmap's keys is O(NlogN)

Categories

Resources