I have a Collection as
Vector<HashMap<String, String>>
Actually I am using this as list items of list view in android.I used SortedMap but I did not get correct result. I think this is because HashMap's structure is
hashMap.add("Name","value_of_name");
hashMap.add("Counts","value_of_counts");
Now I am adding it to Vector.
I want to sort vector's element by Name key of hashMap.
I know about Collection.sort and I can sort this using ArrayList and POJO class. But I do not know how to use it with adapter of my ListView
How can I sort elements. And is there any better solution (Regarding my data-structure of collection, which can be use with adapter easily) ?
You need to a implement a Comparator<HashMap<String,String> > and place the logic of your sort ordering inside its compare method.
Not sure I understand correctly. This will sort the vector on one key of the maps.
Collections.sort(yourVector, new Comparator<HashMap<String,String>>() {
public int compare(HashMap<String,String> a, HashMap<String,String> b) {
return a.get(yourKey).compareTo(b.get(yourKey));
}
});
Have you never thought about taking a look at collections in java.util package ?
You would then have discovered that Treemap already implements balanced tree sorting for Comparable items, like String is.
So, to have your items sorted, just repalce your HashMap with a TreeMap, and all the work will be done.
BTW what does this vector does here ? They're sooo Java 1.1 (fifteen years old, in other words)
If you want to sort the maps in the array, use a SortedMap implementation like TreeMap or ConcurrentSkipListMap. This takes a vector of HashMaps and returns a ArrayList (a non-synchronized and faster collection than Vector) of SortedMaps.
public ArrayList<SortedMap<String, String>> sortMaps(Vector<HashMap<String, String> maps) {
ArrayList<TreeMap<String, String>> returnMaps = new ArrayList<TreeMap<String, String>>();
for(HashMap<String, String> theMap : maps) {
// TreeMap is a sorted map and this will use the default String.compareTo
TreeMap<String, String> newMap = new TreeMap<String, String>();
// put all the items from the HashMap into the TreeMap, which will autosort
newMap.putAll(theMap);
returnMaps.add(newMap);
}
return returnMaps;
}
To sort the Vector by the first keys (lowest keys, first alphabetically) of the hash map try the following before the return line:
// this sorts the vector by first keys
Collections.sort(returnMaps, new Comparator<SortedMap<String,String>>() {
public int compare(SortedMap<String,String> a, HashMap<String,String> b) {
return a.firstKey().compareTo(b.firstKey());
}
});
Or if you want to sort by last key (highest keys, last alphabetically):
// this sorts the vector by first keys
Collections.sort(returnMaps, new Comparator<SortedMap<String,String>>() {
public int compare(SortedMap<String,String> a, HashMap<String,String> b) {
return a.lastKey().compareTo(b.lastKey());
}
});
To return one sorted map of all keys (will stomp on any duplicates):
public SortedMap<String, String> singledSortedMap(Vector<HashMap<String, String> maps) {
// this will end up with all the values, sorted by natural string ordering
SortedMap<String, String> returnMap = new TreeMap<String, String>();
for(HashMap<String, String> theMap : maps) {
returnMap.putAll(theMap);
}
return returnMap;
}
The best (fastest) way it to use a TreeMap instead. If you supply it with the correct Comperator all the items in the TreeMap will be sorted.
The important question: Why do you have a Vector of HashMaps?
Related
I have a TreeMap like so.
// Create a map of word and their counts.
// Put them in TreeMap so that they are naturally sorted by the words
Map<String, Integer> wordCount = new TreeMap<String, Integer>();
wordCount.put("but", 100);
wordCount.put("all", 10);
Since it is a TreeMap the content are sorted by key, i.e. the words.
// Iterate over the map to confirm that the data is stored sorted by words.
// This part is also working nicely and I can see that the ouput is sorted by
// words.
Set<String> words = wordCount.keySet();
logger.debug("word, count");
for (Iterator<String> itForWords = words.iterator(); itForWords.hasNext();) {
String word = (String) itForWords.next();
Integer count = wordCount.get(word);
logger.debug("{}, {}", word, count);
}
Now I am trying to sort them by count. Since TreeMap will not drop the trick I am moving them to a SortedSet.
// Trying to sort the collection by the count now.
// TreeMap cant be sorted on values.
// Lets put them in a sorted set and put a comparator to sort based on values
// rather than keys.
SortedSet<Map.Entry<String, Integer>> wordCountSortedByCount = new TreeSet<Map.Entry<String, Integer>>(
new Comparator<Map.Entry<String, Integer>>() {
#Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
return o1.getValue().compareTo(o1.getValue());
}
});
wordCountSortedByCount.addAll(wordCount.entrySet());
At this point I am expecting the TreeSet to have 2 entries. But it is showing only one. Please help.
// This is NOT WORKING
// The size is only 1. It should have been two.
logger.debug("Size of sorted collection is {}", wordCountSortedByCount.size());
To avoid such errors, it worth to use comparator in Java 8:
Comparator.comparing(Map.Entry::getValue)
SortedSet<Map.Entry<String, Integer>> wordCountSortedByCount =
new TreeSet<>(Comparator.comparing(Map.Entry::getValue));
Modify return o1.getValue().compareTo(o1.getValue()); to
return o1.getValue().compareTo(o2.getValue());
Output will be 2.
I have the following hashmap in java:
{B046=0.0, A061=3.0, A071=0.0, B085=0.0, B075=3.0, B076=9.0, B086=3.0, B095=0.0, B096=0.0, A052=0.0, B066=0.0, B056=9.0, B065=0.0, B055=9.0}
How should I go about sorting the hashmap such that the Alphabet, followed by the numerical figures are taken into account?
The resulting hashmap should look like this:
{A052=0.0,A061=3.0,A071=0.0,B046=0.0,B055=9.0,B056=9.0,B065=0.0,B066=0.0,B075=3.0,B076=9.0,B085=0.0,B086=3.0,B095=0.0,B096=0.0}
Appreciate the help!
Use sorted TreeMap:
Map<String, Float> map = new TreeMap<>(yourMap);
It will automatically put entries sorted by keys. I think natural String ordering will be fine in your case.
Note that HashMap due to lookup optimizations does not preserve order.
Use a TreeMap with a custom comparator.
class MyComparator implements Comparator<String>
{
public int compare(String o1,String o2)
{
// Your logic for comparing the key strings
}
}
TreeMap<String, Float> tm = new TreeMap<String , Float>(new MyComparator());
As you add new elements, they will be automatically sorted.
In your case, it might not even be necessary to implement a comparator because String ordering might be sufficient. But if you want to implement special cases, like lower case alphas appear before upper case, or treat the numbers a certain way, use the comparator.
TreeMap is your best bet for these kind of sorting (Natural). TreeMap naturally sorts according to the keys.
HashMap does not preserve insertion order nor does it sort the map. LinkedHashMap keeps the insertion order but doesn't sort the map automatically. Only TreeMap in the Map interface sorts the map according to natural order (Numerals first, upper-case alphabet second, lower-case alphabet last).
Use a TreeMap, although having a map "look like that" is a bit nebulous--you could also just sort the keys based on your criteria and iterate over the map, retrieving each object.
Use TreeMap (Constructor):
Map<String, Float> sortedMap = new TreeMap<>(yourMap);
Use TreeMap (PutAll method):
Map<String, Float> sortedMap = new TreeMap<>();
sortedMap.putAll(yourMap);
Implementation of Map interface:
TreeMap - Automatically sort the keys in ascending order while inserting.
HashMap - Order of insertion won't be maintained.
LinkedHashMap - Order of insertion will be maintained.
Just use a TreeMap. It implements the SortedMap interface, and thus automatically sorts the keys it contains. Your keys can just be sorted alphabetically to get the desired result, so you don't even need to provide a comparator.
HashMaps are never sorted. The only thing you coulkd do with a HashMap is get all the keys, and store them in a sorted set or in a List and sort the List.
Using the TreeMap you can sort the Map.
Map<String, String> map = new HashMap<String, String>();
Map<String, String> treeMap = new TreeMap<String, String>(map);
//show hashmap after the sort
for (String str : treeMap.keySet()) {
System.out.println(str);
}
You can use TreeMap which will store values in sorted form.
Map <String, String> map = new TreeMap <String, String>();
TreeMap will automatically sort in ascending order. If you want to sort in descending order, use the following code:
Copy the below code within your class and outside of the main execute method:
static class DescOrder implements Comparator<String> {
#Override
public int compare(String o1, String o2) {
return o2.compareTo(o1);
}
}
Then in your logic:
TreeMap<String, String> map = new TreeMap<String, String>(new DescOrder());
map.put("A", "test1");
map.put("C", "test3");
map.put("E", "test5");
map.put("B", "test2");
map.put("D", "test4");
Learning Java as I go (Python background). Simple word count program in Java 7 code (can not use J8!).
I have a hash map of word:count pairs. Now I need to sort on count (decreasing order), and break ties with using word in alphabetical order.
Have read s/o and I tried a treemap but it does not seem to handle ties very well so I don't think that is right.
I have seen a lot of solutions posted that define a new class sortbyvalue and define a comparator. These will not work for me as I need to keep the solution all contained in the existing class.
I am looking for feedback on this idea:
iterate over the map entries (me) in the hashmap
use me.getKey = K and me.getValue = V
new Map.Entry reverse_me = (V,K) {not sure about this syntax}
add reverse_me to a List
repeat for all me in map
List.sort { this is where I am unsure, on how this will sort and no idea how to write a comparator. At this point each List element would be a (count, word) pair and the sort() should sort by count in decreasing and then by word in case of same counts in alphabetical order)
This would be the final output.
Is this a logical progression? I can tell from the many posts that there are many opinions on how to do this, but this is the one I can wrap my head around.
Also, can not use Guava.
You can create an List of Entry set from the map. Sort the List using Collections.sort(). You can pass the custom Comparator for sorting by Key when Value(s) are same.
Set<Entry<String, Integer>> set = map.entrySet();
List<Entry<String, Integer>> list = new ArrayList<Entry<String, Integer>>(set);
Collections.sort( list, new Comparator<Map.Entry<String, Integer>>()
{
public int compare( Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2 )
{
int result = (o2.getValue()).compareTo( o1.getValue() );
if (result != 0) {
return result;
} else {
return o1.getKey().compareTo(o2.getKey());
}
}
} );
This collection reflects the correct order only as long as the map entries are not changed
HashMap<String, Integer> map = new HashMap<>();
TreeSet<Map.Entry<String, Integer>> entriesSet = new TreeSet<>(new Comparator<Map.Entry<String, Integer>>(){
#Override
public int compare(Map.Entry<String, Integer> me1, Map.Entry<String, Integer> me2) {
return me1.getValue().compareTo(me2.getValue());
}
});
entriesSet.addAll(map.entrySet());
I am looking for a container that would basically work like HashMap where I could put and get any of the entries in O(1) time. I also want to be able to iterate through but I want the order to be sorted by values. So neither TreeMap nor LinkedHashMap would work for me. I found the example below:
SortedSet<Map.Entry<String, Double>> sortedSet = new TreeSet<Map.Entry<String, Double>>(
new Comparator<Map.Entry<String, Double>>() {
#Override
public int compare(Map.Entry<String, Double> e1,
Map.Entry<String, Double> e2) {
return e1.getValue().compareTo(e2.getValue());
}});
The problem is SortedSet doesn't have any get method to get entries.
I will be using this collection in a place where I will be adding entries but in case of already existing entry, the value(double) will be updated and then sorted again by using the comparator(which compares values as mentioned above). What can I use for my needs?
There is no such data structure in the Java class libraries.
But you could create one that is a wrapper for a private HashMap and a private TreeMap with the same set of key/value pairs.
This gives a data structure that has get complexity of O(1) like a regular HashMap (but not put or other update operations), and a key Set and entry Set which can be iterated in key order ... as requested in the original version of this Question.
Here is a start for you:
public class HybridMap<K,V> implements Map<K,V> {
private HashMap<K,V> hashmap = ...
private TreeMap<K,V> treemap = ...
#Override V get(K key) {
return hashmap.get(key);
}
#Override void (K key, V value) {
hashmap.put(key, value);
treemap.put(key, value);
}
// etcetera
}
Obviously, I've only implemented some of the (easy) methods.
If you want to be able to iterate the entries in value order (rather than key order), once again there is no such data structure in the Java class libraries.
In this case, wrapping a HashMap and TreeMap is going to be very complicated if you need the resulting Map to conform fully to the API contract.
So I suggest that you just use a HashMap and TreeSet of the key/value pairs ... and manually keep them in step.
This question already has answers here:
Closed 10 years ago.
I have the following HashMap:
HashMap<String, Integer> counts = new HashMap<String, Integer>();
What is the simplest way to order it according to the values?
You can't sort a Map by the values, especially not a HashMap, which can't be sorted at all.
Instead, you can sort the entries:
List<Map.Entry<String, Integer>> entries = new ArrayList<Map.Entry<String, Integer>>(map.entrySet());
Collections.sort(entries, new Comparator<Map.Entry<String, Integer>>() {
public int compare(
Map.Entry<String, Integer> entry1, Map.Entry<String, Integer> entry2) {
return entry1.getValue().compareTo(entry2.getValue());
}
});
will sort the entries in ascending order of count.
You can get a set of entries (Set of Map.Entry) from a map, by using map.entrySet(). Just iterate over them, and check the values by getValue().
A work around, if you want to them print them in order(Not storing).
Create a new Map (tempMap) and put your value as key and key as value. To make the keys unique, please add some unique value in each of the keys e.g. key1 = value1+#0.
Get the list of values as map.values() as list myVlues
Sort the myVlues list as Collections.sort(myVlues)
Now iterate the myVlues, get the corresponding key from tempMap, restore the key e.g. key.substring(0, key.length-2) and print the key and value pair.
Hope this helps.
A TreeMap can keep its entries in an order defined by a Comparator.
We can create a comparator that will order the Map by putting the greatest value first.
Then, we will build a TreeMap that uses that Comparator.
We will then put all the entries in our counts map into the Comparator.
Finally, we will get the first key in the map, which should be the most common word (or at least one of them, if multiple words have equal counts).
public class Testing {
public static void main(String[] args) {
HashMap<String,Double> counts = new HashMap<String,Integer>();
// Sample word counts
counts.put("the", 100);
counts.put("pineapple",5);
counts.put("a", 50);
// Step 1: Create a Comparator that order by value with greatest value first
MostCommonValueFirst mostCommonValueFirst = new MostCommonValueFirst(counts);
// Step 2: Build a TreeMap that uses that Comparator
TreeMap<String,Double> sortedMap = new TreeMap<String,Integer (mostCommonValueFirst);
// Step 3: Populate TreeMap with values from the counts map
sortedMap.putAll(counts);
// Step 4: The first key in the map is the most commonly used word
System.out.println("Most common word: " + sortedMap.firstKey());
}
}
private class MostCommonValueFirst implements Comparator<String> {
Map<String, Integer> base;
public MostCommonValueFirst(Map<String, Integer> base) {
this.base = base;
}
// Note: this comparator imposes orderings that are inconsistent with equals.
public int compare(String a, String b) {
if (base.get(a) >= base.get(b)) {
return 1;
} else {
return -1;
} // returning 0 would merge keys
}
}
Source: https://stackoverflow.com/a/1283722/284685