I have two arrays in my Hash map and I want to sort the values stored in the averageValueArray according to the time in the timeStampArray. I am using TreeMap but I am getting ClassCastException which says that ArrayList is not comparable.
This is what I am doing:
Map<List<Date>,List<Double>> sortMap = new HashMap<List<Date>,List<Double>>();
sortMap.put(timeStampArray, averageValueArray);
for (Map.Entry entry : sortMap.entrySet()) {
System.out.println("Key = " + entry.getKey());
System.out.println(" Value = " +entry.getValue());
}
System.out.println("Unsort Map......");
printMap(sortMap);
System.out.println("Sorted Map......");
TreeMap<List<Date>,List<Double>> treeMap = new TreeMap<List<Date>,List<Double>>(sortMap);
for (Map.Entry entry : treeMap.entrySet()) {
System.out.println("Key = " + entry.getKey());
System.out.println(" Value = " +entry.getValue());
}
printMap(treeMap);
And the printMap is:
public static void printMap(Map<List<Date>,List<Double>> map) {
for (Map.Entry entry : map.entrySet()) {
System.out.println("Key : " + entry.getKey() + " Value : "
+ entry.getValue());}}
As the error message says, ArrayList does not implement the Comparable interface that is required by TreeMap to do the ordering of the elements in the map. You can, however, create the TreeMap with the constructor that takes a Comparator instead, and implement the comparator according to your ordering rules.
From Java doc of TreeMap
A Red-Black tree based NavigableMap implementation. The map is sorted according to the natural ordering of its keys, or by a Comparator provided at map creation time, depending on which constructor is used.
List does not implements Comparable so you need to provide Comparator
I still can't figure out why are you using List. What you need can just be possible using TreeMap<Date, Double>
You need to use a comparator as the key of your tree map doesn't implement the Comparable interface.
There's a TreeMap constructor which accepts a custom Comparator and you can implement that with your custom logic.
Related
I know there are a number of posts that describe how to sort a hashmap in reverse. I've tried them and I've struggled to make it work. I'm relatively new to Java.
Below, I can print the hashmap in order from lowest double to highest double, but how do I sort it so the highest double comes first?
I've followed this post unsuccessfully.
I want to sort the following in reverse order the hashMap called "lines":
public void sortResults(HashMap<Double, TextObject> lines) {
Map<Double,TextObject> sortedMap = new TreeMap<Double,TextObject>(lines);
System.out.println("**************************************");
for (Map.Entry<Double, TextObject> entry : sortedMap.entrySet()) {
System.out.println("Key : " + entry.getKey()
+ " Value : " + entry.getValue());
}
System.out.println();
}
You can create TreeMap with reverse comparator and then use putAll to add lines
Map<Double,TextObject> sortedMap = new TreeMap<Double,TextObject>(Comparator.reverseOrder());
sortedMap.putAll(lines);
I have a TreeMap<Token, ArrayList<Token>> and I want to iterate through the map until a specific key which fulfills a requirement. I know that the following works for getting the values of a map:
Collection c = bigrams.values();
Iterator itr = c.iterator();
while (itr.hasNext()){
System.out.println(itr.next());
However, I want to be able to iterate through the map with the keys linked to the iterator, and check each value based on its pair key. Since bigrams.values() retrieves the value of each of the elements of the bigram, how may I change this to retrieve the keys instead of the values?
Your question is a bit cryptic, but if you want to get the keys, you can simply use the keySet() method:
Collection c = test.keySet();
If you want to iterate through the map based on the keys, you can do:
for (Token key: bigrams.keySet()) {
ArrayList<Token> list = bigrams.get(key);
// do with the list what you want to do with it
}
You should eilter use Map.keySet() or Map.entrySet():
Map.keySet() returns a set containing all keys of your map. You then can use Map.get() to get the value for a given key:
for (Token key: bigrams.keySet()) {
List<Token> list = bigrams.get(key);
System.out.println(key + ": " + list);
}
Map.entrySet() returns a set of all pairs in your map, so there is no need to use Map.get() with this:
for (Map.Entry<Token, List<Token>> entry : bigrams.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
Finally you also can use the Java Stream API for this. You also can use it to filter the content very easily. For example to find all tokens containing a given token in their value list:
bigrams.entrySet().stream()
.filter(e -> e.getValue().contains(tokenToFind))
.forEach(e -> System.out.println(e.getKey() + ": " + e.getValue()));
This question already has answers here:
How do I efficiently iterate over each entry in a Java Map?
(46 answers)
Closed 5 years ago.
How do I search for a Hashmap that contains String as a key and list of objects as value?
HashMap<String,List<PageObjectBaseClass>> ObjList1;
When I used
for (HashMap<String,List<PageObjectBaseClass>> map : ObjList1)
Am getting the error "Can only iterate over an array or an instance of java.lang.Iterable"
You'll need to enumerate over the entrySet like this:
for (Map.Entry<String, List<PageObjectBaseClass>> map : ObjList1.entrySet()){
....
}
There are many ways. The one I find most idiomatic and expressive is Map.forEach:
yourMap.forEach((key, value) -> {
// key is of type String
// value is List<PageObjectBaseClass>
});
You can only use the extended for-loop over objects that implement the Iterable interface. Map does not.
However it provides some utility method to access collections of its entries, keys and values which are of type Iterable. Therefore consider the following examples:
HashMap<A, B> map = new HashMap<>();
// Entries
for (Map.Entry<A, B> entry : map.entrySet​()) { ... }
// Keys
for (A key : map.keySet()) { ... }
// Values
for (B value : map.values()) { ... }
Here are links to the documentation of all three methods:
Map#entrySet - documentation
Map#keySet - documentation
Map#values - documentation
Note that all three accesses are fast, O(1). As you get collections that are internally used by the map. That is also why they are backed by the map, which means if you change something on the collections or the entries, the changes will be reflected inside the map too.
This an example from here
public static void printMap(Map mp) {
Iterator it = mp.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
System.out.println(pair.getKey() + " = " + pair.getValue());
it.remove(); // avoids a ConcurrentModificationException
}
}
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.
Is there a way to start iteration in HashMap from a particular key?
Suppose my map is :
Map map = new HashMap();
map.put(1,"A");
map.put(2,"B");
map.put(3,"B");
map.put(4,"B");
map.put(5,"F");
map.put(6,"Z");
And I want the iteration to start from key 2.
The regular iteration involves :
public static void printMap(Map map) {
Iterator it = map.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pair = (Map.Entry)it.next();
System.out.println(pair.getKey() + " = " + pair.getValue());
}
}
But how to start the iteration from a particular key?
Your question is based on a misunderstanding of what a HashMap is. In particular, if you started at the key 2 and iterated the remaining entries, there is no guarantee that you would get entries with keys 2, 3, 4, 5 and 6 ... in that order, or in any order.
The order of iteration for a HashMap is undefined, and in most cases unpredictable.
However ... if you used a LinkedHashMap or a TreeMap and iterated the entries then you would get them in a defined order:
a LinkedHashMap would (typically) give the entries in insertion order
a TreeMap would give the entries in comparison order of the keys.
If you use a LinkedHashMap, the way to get all entries starting from a given key (in insertion order) is to iterate from the start until you get to the key you want. For example:
public static void printMapFrom(LinkedHashMap<K, V> map, K from) {
boolean found = false;
for (Map<K, V>.Entry entry : map.entrySet()) {
if (!found && !from.equals(entry.getKey())) {
continue;
}
found = true;
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
If you use a TreeMap, the way to do it is to use tailMap(key) to get the submap of entries from the key to the end. Then you iterate the submap.
public static void printMapFrom(SortedMap<K, V> map, K from) {
for (Map<K, V>.Entry entry : map.tailMap(from).entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
If you actually don't care that the order of keys in a HashMap is indeterminate, then you can use the LinkedHashMap version above with a plain HashMap or a ConcurrentHashMap.
first define your map Map<Integer, String> map = new LinkedHashMap<Integer,String>();
And then you can use like it
for(Map.Entry<Integer, String> entry: map.entrySet()){
if(entry.getKey() == 1){
continue;
}
System.out.println(entry.getKey() +" : "+ entry.getValue());
}