Related
I want to create a method that will sort a HashMap by keys. The HashMap's keys can be String or Long. The processing of the two HashMap types is similar. In order to avoid code duplication I want to create a single method to handle both cases.
The method's code:
static LinkedHashMap<Long, Integer> sortNumberHashMapByKey(HashMap<Long, Integer> map){
ArrayList<Long> keys = new ArrayList<>(map.keySet());
ArrayList<Integer> values = new ArrayList<>(map.values());
Collections.sort(keys);
Collections.sort(values);
LinkedHashMap<Long, Integer> sortedMap = new LinkedHashMap<>();
for (Integer value : values) {
Iterator<Long> keyIt = keys.iterator();
while (keyIt.hasNext()){
Long key = keyIt.next();
if (map.get(key).equals(value)){
keyIt.remove();
sortedMap.put(key, value);
break;
}
}
}
return sortedMap;
}
Is it possible to create a Java method with a single argument that can receive values of both HashMap<String, Integer> and HashMap<Long, Integer> types?
You can introduce a T which needs to implement Comparable<T> and then replace any usage of Long with T:
static <T extends Comparable<T>> LinkedHashMap<T, Integer> sortNumberHashMapByKey(HashMap<T, Integer> map){
ArrayList<T> keys = new ArrayList<>(map.keySet());
ArrayList<Integer> values = new ArrayList<>(map.values());
Collections.sort(keys);
Collections.sort(values);
LinkedHashMap<T, Integer> sortedMap = new LinkedHashMap<>();
for (Integer value : values) {
Iterator<T> keyIt = keys.iterator();
while (keyIt.hasNext()){
T key = keyIt.next();
if (map.get(key).equals(value)){
keyIt.remove();
sortedMap.put(key, value);
break;
}
}
}
return sortedMap;
}
You can use Generics in java to define a method that works on a particular type e.i. in your case Sting and Long(both are of Comparable) The code will then look like:
static <E extends Comparable<E>> LinkedHashMap<E, Integer> sortNumberHashMapByKey(HashMap<E, Integer> map){
ArrayList<E> keys = new ArrayList<>(map.keySet());
ArrayList<Integer> values = new ArrayList<>(map.values());
Collections.sort(keys);
Collections.sort(values);
LinkedHashMap<E, Integer> sortedMap = new LinkedHashMap<>();
for (Integer value : values) {
Iterator<E> keyIt = keys.iterator();
while (keyIt.hasNext()){
E key = keyIt.next();
if (map.get(key).equals(value)){
keyIt.remove();
sortedMap.put(key, value);
break;
}
}
}
return sortedMap;
}
Here <E extends Comparable<E>> is the type that you would like to pass to your method. And then use this type E in your code to do the operations that are common to both String and Long.
This question already has answers here:
Sort a Map<Key, Value> by values
(64 answers)
Closed 3 years ago.
How are we able to sort a HashMap<key, ArrayList>?
I want to sort on the basis of a value in the ArrayList.
Do you have to use a HashMap? If you only need the Map Interface use a TreeMap
If you want to sort by comparing values in the HashMap. You have to write code to do this, if you want to do it once you can sort the values of your HashMap:
Map<String, Person> people = new HashMap<>();
Person jim = new Person("Jim", 25);
Person scott = new Person("Scott", 28);
Person anna = new Person("Anna", 23);
people.put(jim.getName(), jim);
people.put(scott.getName(), scott);
people.put(anna.getName(), anna);
// not yet sorted
List<Person> peopleByAge = new ArrayList<>(people.values());
Collections.sort(peopleByAge, Comparator.comparing(Person::getAge));
for (Person p : peopleByAge) {
System.out.println(p.getName() + "\t" + p.getAge());
}
If you want to access this sorted list often, then you could insert your elements into a HashMap<TreeSet<Person>>, though the semantics of sets and lists are a bit different.
Sorted List by hasmap keys:
SortedSet<String> keys = new TreeSet<String>(myHashMap.keySet());
Sorted List by hashmap values:
SortedSet<String> values = new TreeSet<String>(myHashMap.values());
In case of duplicated map values:
List<String> mapValues = new ArrayList<String>(myHashMap.values());
Collections.sort(mapValues);
Good Luck!
http://snipplr.com/view/2789/sorting-map-keys-by-comparing-its-values/
get the keys
List keys = new ArrayList(yourMap.keySet());
Sort them
Collections.sort(keys)
print them.
In any case, you can't have sorted values in HashMap (according to API This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time ].
Though you can push all these values to LinkedHashMap, for later use as well.
Seems like you might want a treemap.
http://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html
You can pass in a custom comparator to it if that applies.
In Java 8:
Comparator<Entry<String, Item>> valueComparator =
(e1, e2) -> e1.getValue().getField().compareTo(e2.getValue().getField());
Map<String, Item> sortedMap =
unsortedMap.entrySet().stream().
sorted(valueComparator).
collect(Collectors.toMap(Entry::getKey, Entry::getValue,
(e1, e2) -> e1, LinkedHashMap::new));
Using Guava:
Map<String, Item> map = ...;
Function<Item, Integer> getField = new Function<Item, Integer>() {
public Integer apply(Item item) {
return item.getField(); // the field to sort on
}
};
comparatorFunction = Functions.compose(getField, Functions.forMap(map));
comparator = Ordering.natural().onResultOf(comparatorFunction);
Map<String, Item> sortedMap = ImmutableSortedMap.copyOf(map, comparator);
Custom compare function which includes functionality for the Turkish alphabet or other different languages than english.
public <K extends Comparable,V extends Comparable> LinkedHashMap<K,V> sortByKeys(LinkedHashMap<K,V> map){
List<K> keys = new LinkedList<K>(map.keySet());
Collections.sort(keys, (Comparator<? super K>) new Comparator<String>() {
#Override
public int compare(String first, String second) {
Collator collator = Collator.getInstance(Locale.getDefault());
//Collator collator = Collator.getInstance(new Locale("tr", "TR"));
return collator.compare(first, second);
}
});
LinkedHashMap<K,V> sortedMap = new LinkedHashMap<K,V>();
for(K key: keys){
sortedMap.put(key, map.get(key));
}
return sortedMap;
}
here is the using example as the following
LinkedHashMap<String, Boolean> ligList = new LinkedHashMap<String, Boolean>();
ligList = sortByKeys(ligList);
Without any more information, it's hard to know exactly what you want. However, when choosing what data structure to use, you need to take into account what you need it for. Hashmaps are not designed for sorting - they are designed for easy retrieval. So in your case, you'd probably have to extract each element from the hashmap, and put them into a data structure more conducive to sorting, such as a heap or a set, and then sort them there.
If you want to combine a Map for efficient retrieval with a SortedMap, you may use the ConcurrentSkipListMap.
Of course, you need the key to be the value used for sorting.
have you considered using a LinkedHashMap<>()..?
public static void main(String[] args) {
Map<Object, Object> handler = new LinkedHashMap<Object, Object>();
handler.put("item", "Value");
handler.put(2, "Movies");
handler.put("isAlive", true);
for (Map.Entry<Object, Object> entrY : handler.entrySet())
System.out.println(entrY.getKey() + ">>" + entrY.getValue());
List<Map.Entry<String, Integer>> entries = new ArrayList<Map.Entry<String, Integer>>();
Collections.sort(entries, new Comparator<Map.Entry<String, Integer>>() {
public int compare(Map.Entry<String, Integer> a,
Map.Entry<String, Integer> b) {
return a.getValue().compareTo(b.getValue());
}
});
}
results into an organized linked object.
item>>Value
2>>Movies
isAlive>>true
check the sorting part picked from here..
I have developed a class which can be used to sort a map on the basis of keys and values. The basic idea is if you have sort a map using keys then create a TreepMap from your Map which will sort the map by keys. And in case of sorting by values create a list from entrySet and sort the list using comparator interface.
Here is the full solution :
public static void main(String[] args) {
Map<String, Integer> unSortedMap = new LinkedHashMap<String, Integer>();
unSortedMap.put("A", 2);
unSortedMap.put("V", 1);
unSortedMap.put("G", 5);
System.out.println("Unsorted Map :\n");
for (Map.Entry<String, Integer> entry : unSortedMap.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
System.out.println("\n");
System.out.println("Sorting Map Based on Keys :\n");
Map<String, Integer> keySortedMap = new TreeMap<String, Integer>(unSortedMap);
for (Map.Entry<String, Integer> entry : keySortedMap.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
System.out.println("\n");
System.out.println("Sorting Map Based on Values :\n");
List<Entry<String, Integer>> entryList = new ArrayList<Entry<String, Integer>>(unSortedMap.entrySet());
Collections.sort(entryList, new Comparator<Entry<String, Integer>>() {
#Override
public int compare(Entry<String, Integer> obj1, Entry<String, Integer> obj2) {
return obj1.getValue().compareTo(obj2.getValue());
}
});
unSortedMap.clear();
for (Entry<String, Integer> entry : entryList) {
unSortedMap.put(entry.getKey(), entry.getValue());
System.out.println(entry.getKey() + " " + entry.getValue());
}
}
Code is properly tested :D
Sorting HashMap by Value:
As others have pointed out. HashMaps are for easy lookups if you change that or try to sort inside the map itself you will no longer have O(1) lookup.
The code for your sorting is as follows:
class Obj implements Comparable<Obj>{
String key;
ArrayList<Integer> val;
Obj(String key, ArrayList<Integer> val)
{
this.key=key;
this.val=val;
}
public int compareTo(Obj o)
{
/* Write your sorting logic here.
this.val compared to o.val*/
return 0;
}
}
public void sortByValue(Map<String, ArrayList<>> mp){
ArrayList<Obj> arr=new ArrayList<Obj>();
for(String z:mp.keySet())//Make an object and store your map into the arrayList
{
Obj o=new Obj(z,mp.get(z));
arr.add(o);
}
System.out.println(arr);//Unsorted
Collections.sort(arr);// This sorts based on the conditions you coded in the compareTo function.
System.out.println(arr);//Sorted
}
A proper answer.
HashMap<Integer, Object> map = new HashMap<Integer, Object>();
ArrayList<Integer> sortedKeys = new ArrayList<Integer>(map.keySet());
Collections.sort(sortedKeys, new Comparator<Integer>() {
#Override
public int compare(Integer a, Integer b) {
return a.compareTo(b);
}
});
for (Integer key: sortedKeys) {
//map.get(key);
}
Note that HashMap itself cannot maintain sorting, as other answers have pointed out. It's a hash map, and hashed values are unsorted. You can thus either sort the keys when you need to and then access the values in order, as I demonstrated above, or you can find a different collection to store your data, like an ArrayList of Pairs/Tuples, such as the Pair found in Apache Commons:
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html
Sorting by key:
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("b", "dd");
map.put("c", "cc");
map.put("a", "aa");
map = new TreeMap<>(map);
for (String key : map.keySet()) {
System.out.println(key+"="+map.get(key));
}
}
I developed a fully tested working solution. Hope it helps
import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) {
try {
BufferedReader in = new BufferedReader(new java.io.InputStreamReader (System.in));
String str;
HashMap<Integer, Business> hm = new HashMap<Integer, Business>();
Main m = new Main();
while ((str = in.readLine()) != null) {
StringTokenizer st = new StringTokenizer(str);
int id = Integer.parseInt(st.nextToken()); // first integer
int rating = Integer.parseInt(st.nextToken()); // second
Business a = m.new Business(id, rating);
hm.put(id, a);
List<Business> ranking = new ArrayList<Business>(hm.values());
Collections.sort(ranking, new Comparator<Business>() {
public int compare(Business i1, Business i2) {
return i2.getRating() - i1.getRating();
}
});
for (int k=0;k<ranking.size();k++) {
System.out.println((ranking.get(k).getId() + " " + (ranking.get(k)).getRating()));
}
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public class Business{
Integer id;
Integer rating;
public Business(int id2, int rating2)
{
id=id2;
rating=rating2;
}
public Integer getId()
{
return id;
}
public Integer getRating()
{
return rating;
}
}
}
HashMap doesnt maintain any order, so if you want any kind of ordering, you need to store that in something else, which is a map and can have some kind of ordering, like LinkedHashMap
below is a simple program, by which you can sort by key, value, ascending ,descending ..( if you modify the compactor, you can use any kind of ordering, on keys and values)
package com.edge.collection.map;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class SortMapByKeyValue {
Map<String, Integer> map = new HashMap<String, Integer>();
public static void main(String[] args) {
SortMapByKeyValue smkv = new SortMapByKeyValue();
smkv.createMap();
System.out.println("After sorting by key ascending order......");
smkv.sortByKey(true);
System.out.println("After sorting by key descindeng order......");
smkv.sortByKey(false);
System.out.println("After sorting by value ascending order......");
smkv.sortByValue(true);
System.out.println("After sorting by value descindeng order......");
smkv.sortByValue(false);
}
void createMap() {
map.put("B", 55);
map.put("A", 80);
map.put("D", 20);
map.put("C", 70);
map.put("AC", 70);
map.put("BC", 70);
System.out.println("Before sorting......");
printMap(map);
}
void sortByValue(boolean order) {
List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(map.entrySet());
Collections.sort(list, new Comparator<Entry<String, Integer>>() {
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
if (order) {
return o1.getValue().compareTo(o2.getValue());
} else {
return o2.getValue().compareTo(o1.getValue());
}
}
});
Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
for (Entry<String, Integer> entry : list) {
sortedMap.put(entry.getKey(), entry.getValue());
}
printMap(sortedMap);
}
void sortByKey(boolean order) {
List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(map.entrySet());
Collections.sort(list, new Comparator<Entry<String, Integer>>() {
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
if (order) {
return o1.getKey().compareTo(o2.getKey());
} else {
return o2.getKey().compareTo(o1.getKey());
}
}
});
Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
for (Entry<String, Integer> entry : list) {
sortedMap.put(entry.getKey(), entry.getValue());
}
printMap(sortedMap);
}
public void printMap(Map<String, Integer> map) {
// System.out.println(map);
for (Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " : " + entry.getValue());
}
}
}
here is the git link
Convert hashmap to a ArrayList with a pair class
Hashmap<Object,Object> items = new HashMap<>();
to
List<Pair<Object,Object>> items = new ArrayList<>();
so you can sort it as you want, or list sorted by adding order.
Sorting HashMap by value in Java:
public class HashMapSortByValue {
public static void main(String[] args) {
HashMap<Long,String> unsortMap = new HashMap<Long,String>();
unsortMap.put(5l,"B");
unsortMap.put(8l,"A");
unsortMap.put(2l, "D");
unsortMap.put(7l,"C" );
System.out.println("Before sorting......");
System.out.println(unsortMap);
HashMap<Long,String> sortedMapAsc = sortByComparator(unsortMap);
System.out.println("After sorting......");
System.out.println(sortedMapAsc);
}
public static HashMap<Long,String> sortByComparator(
HashMap<Long,String> unsortMap) {
List<Map.Entry<Long,String>> list = new LinkedList<Map.Entry<Long,String>>(
unsortMap.entrySet());
Collections.sort(list, new Comparator<Map.Entry<Long,String>> () {
public int compare(Map.Entry<Long,String> o1, Map.Entry<Long,String> o2) {
return o1.getValue().compareTo(o2.getValue());
}
});
HashMap<Long,String> sortedMap = new LinkedHashMap<Long,String>();
for (Entry<Long,String> entry : list) {
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
}
}
I have created an ArrayList of HashMaps and I know how to get all keys and values of all HashMaps in the list, but then I decided to make it complicated and iterate through the ArrayList and get only specific HashMap values(based on keys). I have no idea how to do that.
How can I modify printArrayList method to get only idand sku values from all hashmaps?
Right now I have the following example:
public class HashmapArraylist {
public static void main(String[] args) throws Exception {
Map<String, Object> map1 = new HashMap<>();
map1.put("id", 1);
map1.put("sku", "test1");
map1.put("quantity", 1);
Map<String, Object> map2 = new HashMap<>();
map2.put("id", 2);
map2.put("sku", "test2");
map2.put("quantity", 2);
Map<String, Object> map3 = new HashMap<>();
map3.put("id", 3);
map3.put("sku", "test3");
map3.put("quantity", 3);
ArrayList<Map<String, Object>> arrayList = new ArrayList<>();
arrayList.add(map1);
arrayList.add(map2);
arrayList.add(map3);
printArrayList(arrayList);
}
public static void printArrayList(ArrayList<Map<String, Object>> arrayList) {
for (Map<String, Object> entry : arrayList) {
for (String key : entry.keySet()) {
String value = entry.get(key).toString();
System.out.println(key + " : " + value);
}
System.out.println("-----------");
}
}
}
Your iterator for the arrayList is correct. To retrieve a value from a map, simply provide the key into the 'get' function of the entry. Since your map has a "String" key to an "Object" value, you can use "toString()" on it to get the string from the Object returned from your key.
public static void printArrayList(ArrayList<Map<String, Object>> arrayList) {
for (Map<String, Object> entry : arrayList) {
String myID = entry.get("id").toString();
String mySKU = entry.get("sku").toString();
System.out.print("id:" + myID + " sku: " + mySKU);
System.out.println("-------------------");
}
}
user681574 seems to have already answered your problem, but I will just add one Java8 example code to do the same thing as you need, using streams
public static void printArrayList(ArrayList<Map<String, Object>> arrayList) {
arrayList.stream() //stream out of arraylist
.forEach(map -> map.entrySet().stream() //iterate through each map in the list, create stream out of maps' entryset
.filter(entry -> entry.getKey().equals("id") || entry.getKey().equals("sku")) //filter out only entries that we need (where key is "id" or "sku")
.forEach(idOrSku -> System.out.println(idOrSku.getKey() + ":" + idOrSku.getValue()))); //Iterate through the id/sku entries and print them out just as we want to
}
I need create inverse map - select unique values and for them find keys.
Seems that only way is to iterate all key/value pairs, because entrySet returns set of <key,value> so value not unique?
The values in a map may not be unique. But if they are (in your case) you can do as you wrote in your question and create a generic method to convert it:
private static <V, K> Map<V, K> invert(Map<K, V> map) {
Map<V, K> inv = new HashMap<V, K>();
for (Entry<K, V> entry : map.entrySet())
inv.put(entry.getValue(), entry.getKey());
return inv;
}
Java 8:
public static <V, K> Map<V, K> invert(Map<K, V> map) {
return map.entrySet()
.stream()
.collect(Collectors.toMap(Entry::getValue, Entry::getKey));
}
Example of usage:
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("Hello", 0);
map.put("World!", 1);
Map<Integer, String> inv = invert(map);
System.out.println(inv); // outputs something like "{0=Hello, 1=World!}"
}
Side note: the put(.., ..) method will return the the "old" value for a key. If it is not null you may throw a new IllegalArgumentException("Map values must be unique") or something like that.
Take a look at Google Guava BiMap.
Example usage
Map<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
Map<String, Integer> inverted = HashBiMap.create(map).inverse();
To get an inverted form of a given map in java 8:
public static <K, V> Map<V, K> inverseMap(Map<K, V> sourceMap) {
return sourceMap.entrySet().stream().collect(
Collectors.toMap(Entry::getValue, Entry::getKey,
(a, b) -> a) //if sourceMap has duplicate values, keep only first
);
}
Example usage
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "one");
map.put(2, "two");
Map<String, Integer> inverted = inverseMap(map);
Seems that only way is to iterate all key/value pairs, because entrySet returns set of so value not unique?
It's one way at least. Here's an example:
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "one");
map.put(2, "two");
Map<String, Integer> inverted = new HashMap<String, Integer>();
for (Integer i : map.keySet())
inverted.put(map.get(i), i);
In case of non-unique values, this algorithm will map the last value found to it's key. (Since the iteration order is undefined for most maps, this should be as good as any solution.)
If you really do want to keep the first value found for each key, you could change it to
if (!inverted.containsKey(map.get(i)))
inverted.put(map.get(i), i);
I would give another approach to this problem giving an extra dimension:
duplicate values in EntrySet.
public static void main(String[] args) {
HashMap<Integer, String> s = new HashMap<Integer, String>();
s.put(1, "Value1");
s.put(2, "Value2");
s.put(3, "Value2");
s.put(4, "Value1");
/*
* swap goes here
*/
HashMap<String,List<Integer>> newMap = new HashMap<String, List<Integer>>();
for (Map.Entry<Integer, String> en : s.entrySet()) {
System.out.println(en.getKey() + " " + en.getValue());
if(newMap.containsKey(en.getValue())){
newMap.get(en.getValue()).add(en.getKey());
} else {
List<Integer> tmpList = new ArrayList<Integer>();
tmpList.add(en.getKey());
newMap.put(en.getValue(), tmpList);
}
}
for(Map.Entry<String, List<Integer>> entry: newMap.entrySet()){
System.out.println(entry.getKey() + " " + entry.getValue());
}
}
T result will be that:
1 Value1 2 Value2 3 Value2 4 Value1 Value1 [1, 4] Value2 [2, 3]
Apache Commons Collections also provides a BidiMap interface for bi-directional maps, along with several implementations.
BidiMap JavaDoc
If your values duplicate and you need to store keys in list you can go with
val invertedMap = originalMap.entrySet().stream()
.collect(Collectors.groupingBy(
Map.Entry::getValue,
Collectors.mapping(Map.Entry::getKey, Collectors.toList()))
);
You have to assume that values may be identical, since the Map contract allows it.
In my opinion the best solution lies in using a wrapper. It will contain the original value, and add an id. Its hashCode() function will rely on the id, and you provide a Getter for the original value.
Code would be something like this:
public class MapKey
{
/**
* A new ID to differentiate equal values
*/
private int _id;
/**
* The original value now used as key
*/
private String _originalValue;
public MapKey(String originalValue)
{
_originalValue = originalValue;
//assuming some method for generating ids...
_id = getNextId();
}
public String getOriginalValue()
{
return _originalValue;
}
#Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + _id;
return result;
}
#Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MapKey other = (MapKey) obj;
if (_id != other._id)
return false;
return true;
}
#Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("MapKey value is ");
sb.append(_originalValue);
sb.append(" with ID number ");
sb.append(_id);
return sb.toString();
}
Inverting the map would be something like this:
public Map <MapKey, Integer> invertMap(Map <Integer, String> map)
{
Map <MapKey, Integer> invertedMap = new HashMap <MapKey, Integer>();
Iterator<Entry<Integer, String>> it = map.entrySet().iterator();
while(it.hasNext())
{
//getting the old values (to be reversed)
Entry<Integer, String> entry = it.next();
Integer oldKey = entry.getKey();
String oldValue = entry.getValue();
//creating the new MapKey
MapKey newMapKey = new MapKey(oldValue);
invertedMap.put(newMapKey, oldKey);
}
return invertedMap;
}
Printing the values something like this:
for(MapKey key : invertedMap.keySet())
{
System.out.println(key.toString() + " has a new value of " + invertedMap.get(key));
}
None of this code is tested, but I believe it's the best solution since it makes use of OO inheritance design instead of "c" style checks and allows you to display all the original keys and values.
With Guava
Multimaps.transformValues(Multimaps.index(map.entrySet(), Map.Entry::getValue),
Map.Entry::getKey)
You'll get a multimap (basically a map of lists) in return.
This question already has answers here:
Sort a Map<Key, Value> by values
(64 answers)
Closed 3 years ago.
How are we able to sort a HashMap<key, ArrayList>?
I want to sort on the basis of a value in the ArrayList.
Do you have to use a HashMap? If you only need the Map Interface use a TreeMap
If you want to sort by comparing values in the HashMap. You have to write code to do this, if you want to do it once you can sort the values of your HashMap:
Map<String, Person> people = new HashMap<>();
Person jim = new Person("Jim", 25);
Person scott = new Person("Scott", 28);
Person anna = new Person("Anna", 23);
people.put(jim.getName(), jim);
people.put(scott.getName(), scott);
people.put(anna.getName(), anna);
// not yet sorted
List<Person> peopleByAge = new ArrayList<>(people.values());
Collections.sort(peopleByAge, Comparator.comparing(Person::getAge));
for (Person p : peopleByAge) {
System.out.println(p.getName() + "\t" + p.getAge());
}
If you want to access this sorted list often, then you could insert your elements into a HashMap<TreeSet<Person>>, though the semantics of sets and lists are a bit different.
Sorted List by hasmap keys:
SortedSet<String> keys = new TreeSet<String>(myHashMap.keySet());
Sorted List by hashmap values:
SortedSet<String> values = new TreeSet<String>(myHashMap.values());
In case of duplicated map values:
List<String> mapValues = new ArrayList<String>(myHashMap.values());
Collections.sort(mapValues);
Good Luck!
http://snipplr.com/view/2789/sorting-map-keys-by-comparing-its-values/
get the keys
List keys = new ArrayList(yourMap.keySet());
Sort them
Collections.sort(keys)
print them.
In any case, you can't have sorted values in HashMap (according to API This class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time ].
Though you can push all these values to LinkedHashMap, for later use as well.
Seems like you might want a treemap.
http://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html
You can pass in a custom comparator to it if that applies.
In Java 8:
Comparator<Entry<String, Item>> valueComparator =
(e1, e2) -> e1.getValue().getField().compareTo(e2.getValue().getField());
Map<String, Item> sortedMap =
unsortedMap.entrySet().stream().
sorted(valueComparator).
collect(Collectors.toMap(Entry::getKey, Entry::getValue,
(e1, e2) -> e1, LinkedHashMap::new));
Using Guava:
Map<String, Item> map = ...;
Function<Item, Integer> getField = new Function<Item, Integer>() {
public Integer apply(Item item) {
return item.getField(); // the field to sort on
}
};
comparatorFunction = Functions.compose(getField, Functions.forMap(map));
comparator = Ordering.natural().onResultOf(comparatorFunction);
Map<String, Item> sortedMap = ImmutableSortedMap.copyOf(map, comparator);
Custom compare function which includes functionality for the Turkish alphabet or other different languages than english.
public <K extends Comparable,V extends Comparable> LinkedHashMap<K,V> sortByKeys(LinkedHashMap<K,V> map){
List<K> keys = new LinkedList<K>(map.keySet());
Collections.sort(keys, (Comparator<? super K>) new Comparator<String>() {
#Override
public int compare(String first, String second) {
Collator collator = Collator.getInstance(Locale.getDefault());
//Collator collator = Collator.getInstance(new Locale("tr", "TR"));
return collator.compare(first, second);
}
});
LinkedHashMap<K,V> sortedMap = new LinkedHashMap<K,V>();
for(K key: keys){
sortedMap.put(key, map.get(key));
}
return sortedMap;
}
here is the using example as the following
LinkedHashMap<String, Boolean> ligList = new LinkedHashMap<String, Boolean>();
ligList = sortByKeys(ligList);
Without any more information, it's hard to know exactly what you want. However, when choosing what data structure to use, you need to take into account what you need it for. Hashmaps are not designed for sorting - they are designed for easy retrieval. So in your case, you'd probably have to extract each element from the hashmap, and put them into a data structure more conducive to sorting, such as a heap or a set, and then sort them there.
If you want to combine a Map for efficient retrieval with a SortedMap, you may use the ConcurrentSkipListMap.
Of course, you need the key to be the value used for sorting.
have you considered using a LinkedHashMap<>()..?
public static void main(String[] args) {
Map<Object, Object> handler = new LinkedHashMap<Object, Object>();
handler.put("item", "Value");
handler.put(2, "Movies");
handler.put("isAlive", true);
for (Map.Entry<Object, Object> entrY : handler.entrySet())
System.out.println(entrY.getKey() + ">>" + entrY.getValue());
List<Map.Entry<String, Integer>> entries = new ArrayList<Map.Entry<String, Integer>>();
Collections.sort(entries, new Comparator<Map.Entry<String, Integer>>() {
public int compare(Map.Entry<String, Integer> a,
Map.Entry<String, Integer> b) {
return a.getValue().compareTo(b.getValue());
}
});
}
results into an organized linked object.
item>>Value
2>>Movies
isAlive>>true
check the sorting part picked from here..
I have developed a class which can be used to sort a map on the basis of keys and values. The basic idea is if you have sort a map using keys then create a TreepMap from your Map which will sort the map by keys. And in case of sorting by values create a list from entrySet and sort the list using comparator interface.
Here is the full solution :
public static void main(String[] args) {
Map<String, Integer> unSortedMap = new LinkedHashMap<String, Integer>();
unSortedMap.put("A", 2);
unSortedMap.put("V", 1);
unSortedMap.put("G", 5);
System.out.println("Unsorted Map :\n");
for (Map.Entry<String, Integer> entry : unSortedMap.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
System.out.println("\n");
System.out.println("Sorting Map Based on Keys :\n");
Map<String, Integer> keySortedMap = new TreeMap<String, Integer>(unSortedMap);
for (Map.Entry<String, Integer> entry : keySortedMap.entrySet()) {
System.out.println(entry.getKey() + " " + entry.getValue());
}
System.out.println("\n");
System.out.println("Sorting Map Based on Values :\n");
List<Entry<String, Integer>> entryList = new ArrayList<Entry<String, Integer>>(unSortedMap.entrySet());
Collections.sort(entryList, new Comparator<Entry<String, Integer>>() {
#Override
public int compare(Entry<String, Integer> obj1, Entry<String, Integer> obj2) {
return obj1.getValue().compareTo(obj2.getValue());
}
});
unSortedMap.clear();
for (Entry<String, Integer> entry : entryList) {
unSortedMap.put(entry.getKey(), entry.getValue());
System.out.println(entry.getKey() + " " + entry.getValue());
}
}
Code is properly tested :D
Sorting HashMap by Value:
As others have pointed out. HashMaps are for easy lookups if you change that or try to sort inside the map itself you will no longer have O(1) lookup.
The code for your sorting is as follows:
class Obj implements Comparable<Obj>{
String key;
ArrayList<Integer> val;
Obj(String key, ArrayList<Integer> val)
{
this.key=key;
this.val=val;
}
public int compareTo(Obj o)
{
/* Write your sorting logic here.
this.val compared to o.val*/
return 0;
}
}
public void sortByValue(Map<String, ArrayList<>> mp){
ArrayList<Obj> arr=new ArrayList<Obj>();
for(String z:mp.keySet())//Make an object and store your map into the arrayList
{
Obj o=new Obj(z,mp.get(z));
arr.add(o);
}
System.out.println(arr);//Unsorted
Collections.sort(arr);// This sorts based on the conditions you coded in the compareTo function.
System.out.println(arr);//Sorted
}
A proper answer.
HashMap<Integer, Object> map = new HashMap<Integer, Object>();
ArrayList<Integer> sortedKeys = new ArrayList<Integer>(map.keySet());
Collections.sort(sortedKeys, new Comparator<Integer>() {
#Override
public int compare(Integer a, Integer b) {
return a.compareTo(b);
}
});
for (Integer key: sortedKeys) {
//map.get(key);
}
Note that HashMap itself cannot maintain sorting, as other answers have pointed out. It's a hash map, and hashed values are unsorted. You can thus either sort the keys when you need to and then access the values in order, as I demonstrated above, or you can find a different collection to store your data, like an ArrayList of Pairs/Tuples, such as the Pair found in Apache Commons:
https://commons.apache.org/proper/commons-lang/apidocs/org/apache/commons/lang3/tuple/Pair.html
Sorting by key:
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("b", "dd");
map.put("c", "cc");
map.put("a", "aa");
map = new TreeMap<>(map);
for (String key : map.keySet()) {
System.out.println(key+"="+map.get(key));
}
}
I developed a fully tested working solution. Hope it helps
import java.io.BufferedReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;
public class Main {
public static void main(String[] args) {
try {
BufferedReader in = new BufferedReader(new java.io.InputStreamReader (System.in));
String str;
HashMap<Integer, Business> hm = new HashMap<Integer, Business>();
Main m = new Main();
while ((str = in.readLine()) != null) {
StringTokenizer st = new StringTokenizer(str);
int id = Integer.parseInt(st.nextToken()); // first integer
int rating = Integer.parseInt(st.nextToken()); // second
Business a = m.new Business(id, rating);
hm.put(id, a);
List<Business> ranking = new ArrayList<Business>(hm.values());
Collections.sort(ranking, new Comparator<Business>() {
public int compare(Business i1, Business i2) {
return i2.getRating() - i1.getRating();
}
});
for (int k=0;k<ranking.size();k++) {
System.out.println((ranking.get(k).getId() + " " + (ranking.get(k)).getRating()));
}
}
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public class Business{
Integer id;
Integer rating;
public Business(int id2, int rating2)
{
id=id2;
rating=rating2;
}
public Integer getId()
{
return id;
}
public Integer getRating()
{
return rating;
}
}
}
HashMap doesnt maintain any order, so if you want any kind of ordering, you need to store that in something else, which is a map and can have some kind of ordering, like LinkedHashMap
below is a simple program, by which you can sort by key, value, ascending ,descending ..( if you modify the compactor, you can use any kind of ordering, on keys and values)
package com.edge.collection.map;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public class SortMapByKeyValue {
Map<String, Integer> map = new HashMap<String, Integer>();
public static void main(String[] args) {
SortMapByKeyValue smkv = new SortMapByKeyValue();
smkv.createMap();
System.out.println("After sorting by key ascending order......");
smkv.sortByKey(true);
System.out.println("After sorting by key descindeng order......");
smkv.sortByKey(false);
System.out.println("After sorting by value ascending order......");
smkv.sortByValue(true);
System.out.println("After sorting by value descindeng order......");
smkv.sortByValue(false);
}
void createMap() {
map.put("B", 55);
map.put("A", 80);
map.put("D", 20);
map.put("C", 70);
map.put("AC", 70);
map.put("BC", 70);
System.out.println("Before sorting......");
printMap(map);
}
void sortByValue(boolean order) {
List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(map.entrySet());
Collections.sort(list, new Comparator<Entry<String, Integer>>() {
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
if (order) {
return o1.getValue().compareTo(o2.getValue());
} else {
return o2.getValue().compareTo(o1.getValue());
}
}
});
Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
for (Entry<String, Integer> entry : list) {
sortedMap.put(entry.getKey(), entry.getValue());
}
printMap(sortedMap);
}
void sortByKey(boolean order) {
List<Entry<String, Integer>> list = new LinkedList<Entry<String, Integer>>(map.entrySet());
Collections.sort(list, new Comparator<Entry<String, Integer>>() {
public int compare(Entry<String, Integer> o1, Entry<String, Integer> o2) {
if (order) {
return o1.getKey().compareTo(o2.getKey());
} else {
return o2.getKey().compareTo(o1.getKey());
}
}
});
Map<String, Integer> sortedMap = new LinkedHashMap<String, Integer>();
for (Entry<String, Integer> entry : list) {
sortedMap.put(entry.getKey(), entry.getValue());
}
printMap(sortedMap);
}
public void printMap(Map<String, Integer> map) {
// System.out.println(map);
for (Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " : " + entry.getValue());
}
}
}
here is the git link
Convert hashmap to a ArrayList with a pair class
Hashmap<Object,Object> items = new HashMap<>();
to
List<Pair<Object,Object>> items = new ArrayList<>();
so you can sort it as you want, or list sorted by adding order.
Sorting HashMap by value in Java:
public class HashMapSortByValue {
public static void main(String[] args) {
HashMap<Long,String> unsortMap = new HashMap<Long,String>();
unsortMap.put(5l,"B");
unsortMap.put(8l,"A");
unsortMap.put(2l, "D");
unsortMap.put(7l,"C" );
System.out.println("Before sorting......");
System.out.println(unsortMap);
HashMap<Long,String> sortedMapAsc = sortByComparator(unsortMap);
System.out.println("After sorting......");
System.out.println(sortedMapAsc);
}
public static HashMap<Long,String> sortByComparator(
HashMap<Long,String> unsortMap) {
List<Map.Entry<Long,String>> list = new LinkedList<Map.Entry<Long,String>>(
unsortMap.entrySet());
Collections.sort(list, new Comparator<Map.Entry<Long,String>> () {
public int compare(Map.Entry<Long,String> o1, Map.Entry<Long,String> o2) {
return o1.getValue().compareTo(o2.getValue());
}
});
HashMap<Long,String> sortedMap = new LinkedHashMap<Long,String>();
for (Entry<Long,String> entry : list) {
sortedMap.put(entry.getKey(), entry.getValue());
}
return sortedMap;
}
}