Converting a Map to a List - java

Is there anyone who knows how to convert a Map to a List
I found here something like this :
List<Value> list = new ArrayList<Value>(map.values());
But this is going to store just the value of the Map to the List
What I want to do is : copy the Key & the Value to the List
So, do you know how to achieve this ?

This will give you a List of the Map entries:
List<Map.Entry<Key, Value>> list =
new ArrayList<Map.Entry<Key, Value>>(map.entrySet());
FYI, entries have a getKey() and a getValue() method.

One way you can do is Create a List with adding all the keys like :
List list = new ArrayList(map.keySet());
Then add all the values like :
list.addAll(map.values);
And then probably you have to access with index like:
if map size is 10 , you know that you have 20 elements in the list.
So you have to write a logic to access the key-value from the list with proper calculation of index like: size/2 something like that.
I am not sure if that helps what your requirement is.

Both #Bohemian and #dacwe are right. I'd say moreover: in most cases you do not have to create your own list. Just use map.entrySet(). It returns Set, but Set is just a Collection that allows iterating over its elements. Iterating is enough in 95% of cases.

Try storing the Map.Entrys of the map:
new ArrayList<Entry<Key, Value>>(map.entrySet());
Example:
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("Hello", 0);
map.put("World!", 1);
ArrayList<Entry<String, Integer>> list =
new ArrayList<Entry<String, Integer>>(map.entrySet());
System.out.println(list.get(0).getKey() + " -> " + list.get(0).getValue());
}

Related

How to sort map of JSONObject

I have a map of JSONObject and Integer. I want to sort it in an incremental order using its values, here is what I've done so far:
Map<JSONObject, Integer> unsortedMap = new HashMap<>();
unsortedMap.put(jsonObject2.getJSONObject(key),key1);
Are you sure you want to use an Object as a key in a hashmap? It's normal practice to use immutable values for keys. The slightest change in any of the elements of the JSONObject will change the hash value and you will be unable to get your info back out of the map.
What is the integer value of your map?
Only a suggestion but you may want to check out the Java API for collection and see if there is anything that better suits your needs. Java Collection API
In the past I have wanted a sorted list with no duplicates. I had to first write to a TreeMap and then write to a SortedSet to get the result I wanted. Not code efficient, but I couldn't achieve what I wanted any other way.
Not sure if this is the best option but could help:
public static Map<String, Integer> SortByKey(Map<String, Integer> map)
{
ArrayList<String> sortedKeys =
new ArrayList<String>(map.keySet());
Collections.sort(sortedKeys);
Map<String, Integer> sortedMap = new HashMap<>();
for (String x : sortedKeys)
sortedMap.put(map.get(x), Integer.parseInt(x));
return sortedMap;
}

How to search efficiently return all the values for keys which are in a arraylist

I am having an arraylist which contains a list of numbers. I want to get all the values from the HashMap which has the keys which are in the array list.
For example say the array list contains 1,2,3,4,5,6,7,8,9 list
I want to get all the values for the keys 1,2,3,4,5,6,7,8,9 map
So currently I am implementing
for (i=0;i<list.size;i++){
map_new.put(list.get(),map.get(list.get()))
}
Is there any efficient way to do this?
Your code basically assumes that map.get(list.get()) always returns a value, you can try the following code which first filters the not null values from the list object and then adds to the new Map:
Map<String, Integer> newMap = list.stream().
filter(key -> (map.get(key) != null)).//filter values not present in Map
collect(Collectors.toMap(t -> t, t -> map.get(t)));//now collect to a new Map
In case, if map.get(list.get()) returns null, your code creates a Map with null values in it for which you might end up doing null checks, which is not good, rather you can ensure that your newly created Map always contains a value for each key.
Assuming the signature of list and the map are as following
List<Integer> list;
Map<Integer, Integer> map;
You can use following
for(int a : list){
Integer b = map.get(a);
if(b != null)
// b is your desired value you can store in another collection
}
Which is similar to the procedure you have already used.
As you can access the map in O(1) so the complexity of this code will be O(listsize)
There is not much you can do for efficiency. Still couple of small things you can do considering code example you have given above:
1) Change your for loop to
for(Long num : list)
instead of iterating using index, this will reduce you get calls over list.
2) You can update the existing map , so that you even do not need to iterate.
map.keySet().retainAll(list);
for(Long key: map.keySet()) {
System.out.println(map.get(key));
}
With this existing map will contain only those data whose keys are present in list, but you should use it carefully depending upon rest of the code logic.
You can capitalize on the fact that the keyset of a map is backed by the map itself and modifications to the keyset will reflect back to the map itself. This way, you can use the retainAll() method of the Set interface to reduce the map with a single line of code. Here is an example:
final Map<Integer, String> m = new HashMap<Integer, String>();
m.put(1, "A");
m.put(2, "B");
m.put(3, "C");
m.put(4, "D");
m.put(5, "E");
final List<Integer> al = Arrays.asList(new Integer[] { 2, 4, 5 });
System.out.println(m);
m.keySet().retainAll(al);
System.out.println(m);
This will output:
{1=A, 2=B, 3=C, 4=D, 5=E}
{2=B, 4=D, 5=E}

Get values from HashMap as reference

Is it possible to get list of values from HashMap as a reference
class MyCustomObject {
String name;
Integer id;
MyCustomObject(String name, Integer id){
this.name = name;
this.id = id;
}
}
HashMap<Integer, MyCustomObject> map = new LinkedHashMap<>();
map.put (1, new MyCustomObject("abc",1));
map.put (2, new MyCustomObject("xyz",2));
List<MyCustomObject> list = new ArrayList<>(map.values());
Log.i(TAG,"************ List from HashMap ************");
for (MyCustomObject s : list) {
Log.i(TAG,"name = "+s.name);
}
list.set(0,new MyCustomObject("temp",3));
Log.i(TAG,"************ List from HashMap after update ************");
for (MyCustomObject s : list) {
Log.i(TAG,"name = "+s.name);
}
Log.i(TAG,"************ List from HashMap ************");
List<MyCustomObject> list2 = new ArrayList<>(map.values());
for (MyCustomObject s : list2) {
Log.i(TAG,"name = "+s.name);
}
Output
**************** List from HashMap ***************
name = abc
name = xyz
**************** List from HashMap after update ***************
name = temp
name = xyz
**************** List from HashMap ***************
name = abc
name = xyz
Here if get list of values from HashMap it return deep-copy.
Update
My Requirement
I want list of values from HashMap because I want to access items using their position
I want to preserve order of values
If I modify anything in the extracted list then it should reflect in HashMap too
Please do tell, if any third party library provide such data structure, or what would be best approach to handle this situation
You are creating an new List based on the values of the Map :
List<MyCustomObject> list = new ArrayList<>(map.values());
That's what creates the copy of the values Collection, and changes in that List cannot be reflected in the original Map.
If you modify the Collection returned by map.values() directly (for example, map.values().remove(new MyCustomObject("abc",1))), it will be reflected in the contents of the original Map. You wouldn't be able to call set on the Collection, though, since Collection doesn't have that method.
Collection values()
Returns a Collection view of the values contained in this map. The
collection is backed by the map, so changes to the map are reflected
in the collection, and vice-versa.
So use a Collection and assign values() to it. Or the entrySet().
Try using the map entries which are backed by the map and which you get by calling entrySet(). A list of those almost works like you want it to do (although I'd still advocate you directly use map.put( key, updatedValue ).
Example:
Map<String, Integer> map = new HashMap<>();
map.put( "a", 1 );
map.put( "b", 2 );
//you create a list that's not backed by the map here but that isn't a problem
//since the list elements, i.e. the entries, are backed by the map
List<Entry<String, Integer>> entryList = new ArrayList<>(map.entrySet());
entryList.get(0).setValue( 5 );
System.out.println( map ); //prints: {a=5, b=2} (note that order is a coincidence here)
One final note though: as I already stated in my comment when dealing with a map order is not always deterministic (unless you know you're dealing with an ordered map like TreeMap) and thus using indices may introduces bugs or undesired behavior. That's why you'll want to at least check the key in most cases and thus you either need to use Map.Entry (which btw can't have its key altered, for good reasons) or use the key directly in which case you don't need a list/collection of values or entries anyways.

Get 3 highest values from Map<String,String>

I have a Map<String,String> which has entries like "User1","43". Now I want a "Top 3" of the highest values.
It would be easier with a Map<String,Integer>, but due to technical limitations I can just grab the Map as a <String,String>.
What's the most efficient way to convert a <String,String> map to a <String,Int> one and then sort it?
To convert from <String, String> to <String, Integer> you can use:
Map<String, Integer> treemap = new HashMap<String, Integer>();
for (Entry<String, String> entry : entries) {
treemap.put(entry.getKey(), Integer.parseInt(entry.getValue()));
}
However, then you will have to iterate the Map again. If you don't need the whole map, but rather just the top 3, then you can simply iterate the entries and get the top three by comparison.
Or you can reverse the key and value and use a TreeMap<Integer, String> with a Comparator, if you need both the top elements and the whole data.
There are a few ways:
Create SortedMap, e.g. TreeMap with a custom -anonymous- Comparator which performs comparisons by looking up the keys it gets in the compare() method call against the values in the original map.
Populate it with all key/value entries in the original through addAll() method.
Watch the map being sorted by value.
Grab the head/tail (depending on how your comparator sorts)
Similar to above:
Create a TreeSet of keys with a custom comparator as above...
Populate it with the keySet() of your original map.
Grab the head/tail set of the keys.
Create a new Map from those keys and value from the original map...
You could just put the values in a List and sort it:
ArrayList<Integer> highest = new ArrayList<Integer>();
for (String value : map.values()) {
highest.add(Integer.parseInt(value));
}
Collections.sort(highest);
for(int i = highest.size() - 1; i >=0 && i > highest.size()-4; i--){
System.out.println(highest.get(i));
}
If the map is very large it might be better to iterate through it and only select the 3 highest values without sorting the whole list.
You could iterate through the values of the Map (with Map.values()), converting each to an Integer (with Integer.getInteger(String s)), and keeping track of the top 3 you see.
Or, you could do as above but instead of keeping track of the top 3, make a LinkedList and insert each Integer at the correct place (traverse the LinkedList until you find where the Integer should be inserted).

How can I sort the keys of a Map in Java?

This is a very basic question, I'm just not that good with Java. I have a Map and I want to get a list or something of the keys in sorted order so I can iterate over them.
Use a TreeMap, which is an implementation of the SortedMap interface. It presents its keys in sorted order.
Map<String, Object> map = new TreeMap<String, Object>();
/* Add entries to the map in any order. */
...
/* Now, iterate over the map's contents, sorted by key. */
for (Map.Entry<String, ?> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
If you are working with another Map implementation that isn't sorted as you like, you can pass it to the constructor of TreeMap to create a new map with sorted keys.
void process(Map<String, Object> original) {
Map<String, Object> copy = new TreeMap<String, Object>(original);
/* Now use "copy", which will have keys in sorted order. */
...
}
A TreeMap works with any type of key that implements the Comparable interface, putting them in their "natural" order. For keys that aren't Comparable, or whose natural ordering isn't what you need, you can implement your own Comparator and specify that in the constructor.
You have several options. Listed in order of preference:
Use a SortedMap:
SortedMap<whatever> myNewMap = new TreeMap<whatever>(myOldMap);
This is vastly preferable if you want to iterate more than once. It keeps the keys sorted so you don't have to sort them before iterating.
There is no #2.
There is no #3, either.
SortedSet<whatever> keys = new TreeSet<whatever>(myMap.keySet());
List<whatever> keys = new ArrayList<whatever>(myMap.keySet());
Collections.sort(keys);
The last two will get you what you want, but should only be used if you only want to iterate once and then forget the whole thing.
You can create a sorted collection when iterating but it make more sense to have a sorted map in the first place. (As has already been suggested)
All the same, here is how you do it.
Map<String, Object> map;
for(String key: new TreeSet<String>(map.keySet()) {
// accessed in sorted order.
}
Apart from the methods mentioned in other answers, with Java 8 streams, another shorthand to get a sorted key list from a map would be -
List<T> sortedKeys = myMap.keySet().stream().sorted().collect(Collectors.toList());
One could actually get stuff done after .sorted() as well (like using a .map(...) or a .forEach(...)), instead of collecting it in the list and then iterating over the list.

Categories