I am using ArrayMap in my Activity for storing my response.
ArrayMap<String, PublicSpotData> publicSpotData ArrayMap will store index as well as key-value pair. Now I have problem in sorting ArrayMap. I want to sort ArrayMap according to publicSpotData.getAt() (int).
I have already done this.
List<Map.Entry<String, PublicSpotData>> entries = new ArrayList<>();
for (Map.Entry<String, PublicSpotData> entry : publicSpotData.entrySet()) {
entries.add(entry);
}
Collections.sort(entries, new Comparator<Map.Entry<String, PublicSpotData>>() {
#Override
public int compare(Map.Entry<String, PublicSpotData> o1, Map.Entry<String, PublicSpotData> o2) {
return o2.getValue().getAt().compareTo(o1.getValue().getAt());
}
});
for (Map.Entry<String, PublicSpotData> entry : entries)
publicSpotData.put(entry.getKey(), entry.getValue());`
But this not solved my issue.
Any help would be appreciated.
you can use Collections#sort method
Collections.sort(new ArrayList<>(c), aComparator);
c is just a key set from the ArrayMap
and aComparator is a custom implemetation of comparator to sort the elemets in the map
You can sort any Java collection by providing a Comparator.
In other words: you have to create a class that knows how to compare two PublicSpotData objects; and then you use that with Collections.sort().
Meaning: as long as your "incoming" object implements one of the Java collection interfaces (and the Android ArrayMap is a Map, which is a collection); you can sort it using the default means of the java library.
But then, the problem is more complicated: you can only sort Lists. And your input data ... is represented as Map. So, lets go step by step:
List<PublicSpotData> dataObjects = ... coming from somewhere
Collections.sort(dataObjects, new Comparator<PublicSpotData>() { ...
here you put the comparator for that thing);
Now you got a list that is sorted for that criteria.
In that sense: the real problem is that your model doesn't support your needs. The essence of a Map is to provide that mapping functionality.
You need to:
extract a list of data objects
sort those
iterate the sorted list; and for each entry ... find the corresponding map key!
Firstly ArrayMap implements sorting implicitly for keys.
Baseline: You need to iterate the arrayMap to obtain Key by index. then call value by that key.
Here is an example of that. I list sorted outputs from unsorted inputs. then I sort the sort the keySet reversely.
ArrayMap<String, String> arrayMap = new ArrayMap<>();
arrayMap.put("AAA7", "BBB2");
arrayMap.put("AAA8", "BBB1");
arrayMap.put("AAA9", "BBB");
arrayMap.put("AAA9", "BBB");// will override previous call
String res = "";
for (int i = 0; i < arrayMap.size(); i++) {
String key = arrayMap.keyAt(i);
res += arrayMap.get(key) + ", ";
}
Log.d(TAG, "normal output: " + res);
// sorting array based on keys
List<String> list = new ArrayList<>(arrayMap.keySet());
java.util.Collections.reverse(list);//or you implement your own sort
String res2 = "";
for (String key : list) {
res2 += arrayMap.get(key) + ", ";
}
Log.d(TAG, "output of sorted collection in reverse based on keys: " + res2);
For more efficiency, you might use SimpleArrayMap if you don't need standard Java API like Iteration.
Related
This question already has answers here:
Sorting hashmap based on keys
(9 answers)
Closed 3 years ago.
I want to sort the following hashmap by value. Hashmap is Hashmap<String, Arraylist<String>> and the data in it is as following:
924911637601767=[1, John]
864467483673342=[2, Paul]
825398867568656=[8, James]
1034643283235161=[5,Elina]
I want to sort the above data with respect to the counter values i.e 1,2,8,5
After Sorting
924911637601767=[1, John]
864467483673342=[2, Paul]
1034643283235161=[5,Elina]
825398867568656=[8, James]
HashMap no guarantees as to the order.
If you want get list by order like you want, you should sort list values of the HashMap.
Example can be found here How to sort a HashMap in Java
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.
See http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
In other words, what you are looking for cannot be achieved as you want.
However, what you can do is to transform your Hashmap to a list of objects that consist of each map entry elements.
Object: key, name, number for example.
Your object can then implement java.lang.Comparable in order to sort it as you want.
See https://docs.oracle.com/javase/tutorial/collections/interfaces/order.html
The hashmap abstract data type is inherently unsorted. Depending on your use case, you could do something like:
import java.util.*;
class Test {
public static void main(String[] args) {
Map<String, List<String>> map = new HashMap<>();
map.put("924911637601767", Arrays.asList("1", "John"));
map.put("864467483673342", Arrays.asList("2", "Paul"));
map.put("825398867568656", Arrays.asList("8", "James"));
map.put("1034643283235161", Arrays.asList("5", "Elina"));
List<Map.Entry<String,List<String>>> entries = new ArrayList<Map.Entry<String,List<String>>>(map.entrySet());
Collections.sort(entries, new Comparator<Map.Entry<String,List<String>>>() {
public int compare(Map.Entry<String,List<String>> l1, Map.Entry<String,List<String>> l2) {
return l1.getValue().get(0).compareTo(l2.getValue().get(0));
}
});
for (Map.Entry<String,List<String>> e : entries) {
System.out.println(e.getKey() + " : [" + e.getValue().get(0)
+ ", " + e.getValue().get(1) + "]");
}
}
}
Use the sortedMap Interface if you are interested in sorted order and also want to keep a map.
TreeMap could be a choice.
http://docs.oracle.com/javase/7/docs/api/java/util/TreeMap.html
In a Java class I have a method to reOrder an existing HashMap by date. The HashMap is of a type <String, Object> where the Object contains a field called expPayDate and the key string is a sequential number turned into a string.. So I need to loop through the items in the sourceMap and find the item with the newest date then copy it to a tempMap in the correct order. My issue is what is the best way to determine the item with the newest date.
Your best bet will be to use a SortedMap with the Comparator interface.
Here is an example:
public SortedMap<String, Object> getSortedMap(Map<String, Object> originalMap) {
SortedMap<String, Object> tmpMap = new TreeMap<String, Object>(new Comparator<String>(){
#Override
public int compare(String key1, String key2) {
//logic for comparing dates
}
});
tmpMap.putAll(originalMap);
return tmpMap;
}
Use a TreeMap instead of HashMap. it will be sorted automatically on insertion.
Map< Date, Object> m = new TreeMap< Date, Object>();
Alternatively, if you have an existing HashMap and want to create a TreeMap based on it, pass it to the constructor:
Map< Date, Object> sortedMap = new TreeMap< Date, Object>(m);
Hope it will help you.
For simplicity I am assuming that type of your map is something more like Map<String, MyClass> map where MyClass has method like getDate() which returns expPayDate.
My issue is what is the best way to determine the item with the newest date.
If you want to find single map entry which value contains max date you don't need to sort entire map which at best would give you O(n*logn). What you need is simple iteration of all elements in map and comparing them with current max, which will be O(n) operation.
You can use stream() (functionality added in Java 8) and its max method. This method needs Comparator and you can easily create one by using comparing method and passing lambda expression which will return value which should be used when comparing.
So your code can look like
//import java.util.Map.Entry;
Optional<Entry<String, MyClass>> max = map.entrySet().stream()
.max(Comparator.comparing(e -> e.getValue().getDate()));
Entry<String, MyClass> entry = max.get();
MyClass maxMC = entry.getValue();
If you can't use Java 8 you can write your own method which will iterate over elements and find max. Such method can look like
public static <T> T max(Iterable<T> iterable, Comparator<T> comp) {
Iterator<T> it = iterable.iterator();
T max = null;
if (it.hasNext()) {
max = it.next();
}
while (it.hasNext()) {
T tmp = it.next();
if (comp.compare(max, tmp) < 0)
max = tmp;
}
return max;
}
and you can use it like
Comparator<Entry<String, MyClass>> myComparator = new Comparator<Entry<String, MyClass>>() {
#Override
public int compare(Entry<String, MyClass> o1, Entry<String, MyClass> o2) {
return o1.getValue().getDate().compareTo(o2.getValue().getDate());
}
};
Entry<String, MyClass> maxEntry = max(map.entrySet(), myComparator);
MyClass max = maxEntry.getValue();
Get all Entries by calling entrySet() method of Map
Create a custom Comparator to sort entries based upon values
Convert Entry set to List
Sort Entry list by using Collections.sort() method by passing your value comparator
Create a LinkedHashMap by adding entries in sorted order.
Look at example code # Sort HasMap by value
If you just need the minimum or maximum date, a simple for each loop might be sufficient:
Date maxDate = null;
for (Entry<String, Object> item: hashMap.entrySet())
if (maxDate == null || maxDate before((Date)item.getValue()))
maxDate = (Date)item.getValue();
This way complexity is only O(n) and insert and delete operations are cheaper than using a sortedMap. Anyway, I think patstuart's suggestion (using a sortedMap) is more elegant.
The correct solution depends on your performance constraints.
If your issue is just finding the item with the newest date, then if O(n) performance is OK you can do a scan of the values() in your HashMap and find the minimum that way.
It depends on how often you need to do this relative to other access on the data structure. It would be perfectly reasonable to use a SortedMap or use a secondary data structure such as a PriorityQueue (acting as a heap on the date), depending on your access patterns for this data structure.
I have Map in Java
Map<String, List<String>> Collections;
String - a parents to ExpandtableList
List -a children to Expandtable List
Example Values
<"12" , "5,6,7,8">
<"15" , "4,6,2,8">
<"17" , "1,6,7,8">
<"8" , "5,6,6,8">
I'd like to get second parent and atribute to temporary String variable.(it is a "17") How can i refer to 2-nd parent and return value ?
There is no ordering in HashMap. If you want to focused on Order with Map you should use LinkedHashMap.
Use LinkedHashMap instead of HashSet. LinkedHashMap will maintain the insertion order.
Well, if you want "17" then you can just write map.get("17") to get the List.
Java doesnt keep track of the order here as it uses a Set to store the data. map.keySet() will return you a set you can iterate through.
You can HOPE that 17 falls under the natural ordering that Java does and do something like this.
HashMap<String, List<String>> map = new HashMap<>();
int count = 0;
for (String key : map.keySet()) {
count++;
if (count == 2)
return map.get(key);
}
If you want to retain an order in a Map, your usual choice would be a LinkedHashMap. With a linked hash map, you do however still not have direct access to an entry by its index. You would need to write a helper function:
static List<String> indexList(LinkedHashMap<String, List<String>> map, int index) {
int i = 0;
for(Map.Entry<String, List<String>> entry : map.entrySet()) {
if(i++ == index) {
return entry.getValue();
}
}
throw new IndexOutOfBoundException();
}
When using maps that point to a list, you might also be interested in using Guava's Multimap.
Good day, this is kind of confusing me now(brain freeze!) and seem to be missing something. Have an ArrayList which i populate with a HashMap. now i put in my HashMap and arraylist.
Map.put(DATE, value1);
Map.put(VALUE, value2);
arraylist.put(Map);
Since am parsing a JSON, the arraylist increases in significant size. now my question is how do you get the values from both map keys in the arraylist? i have tried this
if(!list.isEmpty()){ // list is an ArrayList
for(int k = 0; k < list.size(); k++){
map = (HashMap)list.get(k);
}
}
Log.d(TAG, "map size is" + map.size());
String [] keys = new String[map.size()];
String [] date_value = new String[map.size()];
String [] value_values = new String[map.size()];
int i = 0;
Set entries = map.entrySet();
Iterator iterator = entries.iterator();
while(iterator.hasNext()){
Map.Entry mapping = (Map.Entry)iterator.next();
keys[i] = mapping.getKey().toString();
date_value[i] = map.get(keys[i]);
if(keys[i].equals(DATE)){
date_value[i] = map.get(keys[i]);
} else if(keys[i].equals(VALUE)){
value_values[i] = map.get(keys[i]);
}
i++;
}
But i can't seem to get all the values. the Map size always return a value of 2, which is just the elements. how can i get all the values from the Map keys in the ArrayList? Thanks
Why do you want to re-invent the wheel, when you already have something to do your work. Map.keySet() method gives you a Set of all the keys in the Map.
Map<String, Integer> map = new HashMap<String, Integer>();
for (String key: map.keySet()) {
System.out.println("key : " + key);
System.out.println("value : " + map.get(key));
}
Also, your 1st for-loop looks odd to me: -
for(int k = 0; k < list.size(); k++){
map = (HashMap)list.get(k);
}
You are iterating over your list, and assigning each element to the same reference - map, which will overwrite all the previous values.. All you will be having is the last map in your list.
EDIT: -
You can also use entrySet if you want both key and value for your map. That would be better bet for you: -
Map<String, Integer> map = new HashMap<String, Integer>();
for(Entry<String, Integer> entry: map.entrySet()) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
P.S.: -
Your code looks jumbled to me. I would suggest, keep that code aside, and think about your design one more time. For now, as the code stands, it is very difficult to understand what its trying to do.
List constructor accepts any data structure that implements Collection interface to be used to build a list.
To get all the keys from a hash map to a list:
Map<String, Integer> map = new HashMap<String, Integer>();
List<String> keys = new ArrayList<>(map.keySet());
To get all the values from a hash map to a list:
Map<String, Integer> map = new HashMap<String, Integer>();
List<Integer> values = new ArrayList<>(map.values());
Try it this way...
I am considering the HashMap with key and value of type String, HashMap<String,String>
HashMap<String,String> hmap = new HashMap<String,String>();
hmap.put("key1","Val1");
hmap.put("key2","Val2");
ArrayList<String> arList = new ArrayList<String>();
for(Map.Entry<String,String> map : hmap.entrySet()){
arList.add(map.getValue());
}
Create an ArrayList of String type to hold the values of the map. In its constructor call the method values() of the Map class.
Map <String, Object> map;
List<Object> list = new ArrayList<Object>(map.values());
Put i++ somewhere at the end of your loop.
In the above code, the 0 position of the array is overwritten because i is not incremented in each loop.
FYI: the below is doing a redundant search:
if(keys[i].equals(DATE)){
date_value[i] = map.get(keys[i]);
} else if(keys[i].equals(VALUE)){
value_values[i] = map.get(keys[i]);
}
replace with
if(keys[i].equals(DATE)){
date_value[i] = mapping.getValue();
} else if(keys[i].equals(VALUE)){
value_values[i] = mapping.getValue()
}
Another issue is that you are using i for date_value and value_values. This is not valid unless you intend to have null values in your array.
This is incredibly old, but I stumbled across it trying to find an answer to a different question.
my question is how do you get the values from both map keys in the arraylist?
for (String key : map.keyset()) {
list.add(key + "|" + map.get(key));
}
the Map size always return a value of 2, which is just the elements
I think you may be confused by the functionality of HashMap. HashMap only allows 1 to 1 relationships in the map.
For example if you have:
String TAG_FOO = "FOO";
String TAG_BAR = "BAR";
and attempt to do something like this:
ArrayList<String> bars = ArrayList<>("bar","Bar","bAr","baR");
HashMap<String,String> map = new HashMap<>();
for (String bar : bars) {
map.put(TAG_BAR, bar);
}
This code will end up setting the key entry "BAR" to be associated with the final item in the list bars.
In your example you seem to be confused that there are only two items, yet you only have two keys recorded which leads me to believe that you've simply overwritten the each key's field multiple times.
Suppose I have Hashmap with key datatype as KeyDataType
and value datatype as ValueDataType
HashMap<KeyDataType,ValueDataType> list;
Add all items you needed to it.
Now you can retrive all hashmap keys to a list by.
KeyDataType[] mKeys;
mKeys=list.keySet().toArray(new KeyDataType[list.size()]);
So, now you got your all keys in an array mkeys[]
you can now retrieve any value by calling
list.get(mkeys[position]);
Java 8 solution for produce string like "key1: value1,key2: value2"
private static String hashMapToString(HashMap<String, String> hashMap) {
return hashMap.keySet().stream()
.map((key) -> key + ": " + hashMap.get(key))
.collect(Collectors.joining(","));
}
and produce a list simple collect as list
private static List<String> hashMapToList(HashMap<String, String> hashMap) {
return hashMap.keySet().stream()
.map((key) -> key + ": " + hashMap.get(key))
.collect(Collectors.toList());
}
It has method to find all values from map:
Map<K, V> map=getMapObjectFromXyz();
Collection<V> vs= map.values();
Iterate over vs to do some operation
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?