I have a populated hashmap in the form Hashmap<String , ArrayList<Double>>. There are many cases in which the values (Arraylist) are the same. What I want tro do is if the value is same , the two separate entries should be changed to one with a change in the key. For eg:
HashMap<String, ArrayList<Double>> map = new HashMap<>();
ArrayList<Double> arr = new ArrayList<>();
arr.add(1);
arr.add(2)
map.put("a",arr);
map.put("b",arr);
map.put("c",arr);
This should result in a hashmap with a single entry :
{a, b , c=[1,2]}
I have tried to solve this for hours but am still unable to do so. A million thanks in advance.
Creating your custom HashMap by overriding put() should work, performance-wise it is not really efficient though.
Something like this:
public class CustomMap extends HashMap<String, ArrayList<Double>> {
#Override
public ArrayList<Double> put(String key, ArrayList<Double> value) {
for (Entry<String, ArrayList<Double>> entry : entrySet()) {
if (entry.getValue().equals(value)) {
String oldKey = entry.getKey();
remove(oldKey);
String newKey = oldKey + ", " + key;
return super.put(newKey, value);
}
}
return super.put(key, value);
}
}
To use it, just replace the following:
HashMap<String, ArrayList<Double>> map = new HashMap<>();
With:
CustomMap map = new CustomMap();
Maps relate keys with values. So even if the values are the same, you can't combine these entries because the keys are different
Related
I was wondering if it is possible to get a random value from a HashMap and then straight after remove that key/value from the HashMap? I can't seem to find any method that works, would a different data structure be more appropriate for this?
Edit:
I should've been more clear, I generate a random number and then retrieve the value that corresponds with that random number. I need to return the value and then remove the entry from the map.
Maybe Map#computeIfPresent would work in your case. From its documentation:
If the value for the specified key is present and non-null, attempts to compute a new mapping given the key and its current mapped value.
If the remapping function returns null, the mapping is removed.
var map = new HashMap<Integer, String>();
map.put(1, "One");
map.put(2, "Two");
map.put(3, "Three");
map.computeIfPresent(2, (k, v) -> {
// `v` is equal to "Two"
return null; // Returning `null` removes the entry from the map.
});
System.out.println(map);
The above code outputs the following:
{1=One, 3=Three}
If you were to use a ConcurrentHashMap, then this would be an atomic operation.
The best way to both return and remove the key-value pair from a HashMap is by using the remove(key) method. This method removes the entry associated with the key and returns its corresponding value.
Integer randomNumber = new Random().nextInt(10);
Map<Integer, String> map = new HashMap<>();
String valueOfRandomNumberKey = map.remove(randomNumber);
The problem, as I understand it, is this: given a HashMap you want to
Choose a key at random from among the the keys currently associated in the Map;
Remove that association of that randomly chosen key from the map; and
Return the value that had, until recently, been associated with that key
Here's an example of how to do this, along with some a little test/demonstration routine:
public class Main
{
private static <K, V> V removeRandomEntry(Map<K, V> map){
Set<K> keySet = map.keySet();
List<K> keyList = new ArrayList<>(keySet);
K keyToRemove = keyList.get((int)(Math.random()*keyList.size()));
return map.remove(keyToRemove);
}
public static void main(String[] args){
Map<String, String> map = new HashMap<>();
for(int i = 0; i < 100; ++i)
map.put("Key" + i, "Value"+i);
int pass = 0;
while (!map.isEmpty())
System.out.println("Pass " + (++pass) + ": Removed: " + removeRandomEntry(map));
}
}
I would do it like this:
Hashmap<Integer, Object> example;
int randomNum = ThreadLocalRandom.current().nextInt(0, example.size());
example.getValue() //do something
example.remove(new Integer(randomNum));
learning Java and have figured out how to store a hashmap in an array. But I can't figure out how to get to the stored data. Here is a simplified version of what I'm doing. I've got as far as displaying the specific array items, but how do I access the hash map stored in the array?
import java.util.*;
public class HelloWorld {
public static void main(String[] args) {
Map<String, String> custOrder = new HashMap<String, String>();
List ordersPlaced = new ArrayList();
custOrder.put("colour", "blue");
custOrder.put("manu", "bmw");
custOrder.put("body", "4x4");
ordersPlaced.add(custOrder);
custOrder = new HashMap();
custOrder.put("colour", "green");
custOrder.put("manu", "merc");
custOrder.put("body", "saloon");
ordersPlaced.add(custOrder);
System.out.println(ordersPlaced.get(0).toString());
}
}
Hope that makes sense. Thanks in advance
Neil
You're already accessing it.
In order to get the iterate on the map's items, you can:
ordersPlaced.get(0).forEach((key, value) -> {
System.out.println("Key is: " + key + ", Value is: " + value);
});
Or, earlier to Java 8, something like:
for (Map.Entry<String, String> entry : ordersPlaced.get(0).entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
}
Please note that you should avoid using raw type list. Instead, you should have:
List<Map<String, String>> ordersPlaced = new ArrayList<>();
And then:
Map<String, String> m = ordersPlaced.get(0);
You know it already.
You can get back the stored map by writing
Map<String, String> placedCustOrder = ordersPlaced.get(0);
And avoid using raw types while using List. Declare your list as
List<Map<String, String>> ordersPlaced = new ArrayList<>();
I would like to know how to access the colour of the data stored in the array at location 0
Since you got the map as I said in the line 1
Map<String, String> placedCustOrder = ordersPlaced.get(0);
String colorVal = placedCustOrder.get("colour");
I strongly suggest you to look through Map documentation before proceeding further.
public class MapCheck {
public static void main(String[] args) {
Map<String, String> data = new HashMap<String, String>();
data.put("John", "Taxi Driver");
data.put("Mark", "Professional Killer");
Map<String, String> data1 = new HashMap<String, String>();
data1.put("John", "Driver");
data1.put("Mark", "Murderer");
Map<String, String> data3 = new HashMap<String, String>();
data3.putAll(data);
data3.putAll(data1);
System.out.println(data3);
}
}
I have few maps which contains same key, their values are different. I want to merge them. But when I merge them with the usual putAll() it gives me only the value of the key which was inserted latest.
Output from above code is {John=Driver, Mark=Murderer}
Is there a method which will get me all the values associated with the key and give me as a array like
{John=[Taxi Driver, Driver], Mark=[Professional Killer, Murderer]}
You can produce a Map<String, List<String>> quite easily with Java 8 Streams:
Map<String, List<String>>
merged =
Stream.of(data,data1) // create a Stream<Map<String,String> of all Maps
.flatMap(map->map.entrySet().stream()) // map all the entries of all the
// Maps into a
// Stream<Map.Entry<String,String>>
.collect(Collectors.groupingBy(Map.Entry::getKey, // group entries by key
Collectors.mapping(Map.Entry::getValue,
Collectors.toList())));
The output Map:
{John=[Taxi Driver, Driver], Mark=[Professional Killer, Murderer]}
Something like this?
void add(String key, String value, Map<String,List<String>> map) {
List<String> list = map.get(key);
if (list == null) {
list = new ArrayList<>();
map.put(key, list);
}
list.add(value);
}
the data structure Multimap may be the best choice. The implementation in guava is highly recommended.
https://github.com/google/guava/wiki/NewCollectionTypesExplained#multimap
You may want to create Map<String, <ArrayList<String>>. That way you can store multiple values that are associated with one key.
You may consider creating method that provides storing multiple values associated to unique key in specified map:
public static void add(String key, String value, Map<String, List<String>> map) {
// Here you create a refeREnce to instance of the list storing values associated with given key:
List<String> listOfValues = map.get(key);
// If given key was already present in the map...
if(listOfValues != null) {
// Add given value to list of values associated with given key:
listOfValues.add(value);
// If given key wasn't present in the map...
} else {
// Initialize an ArrayList that will store given value in the map:
listOfValues = new ArrayList<>();
// Put new entry into the given map (given key and to-be-filled list of values:
map.put(key, listOfValues);
// Put given value to the list of values associated with given key
listOfValues.add(value);
}
}
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 am trying to use a HashMap to map a unique string to a string ArrayList like this:
HashMap<String, ArrayList<String>>
Basically, I want to be able to access the keys by number, not by using the key's name. And I want to be able to access said key's value, to iterate over it. I'm imagining something like this:
for(all keys in my hashmap) {
for(int i=0; i < myhashmap.currentKey.getValue.size(); i++) {
// do things with the hashmaps elements
}
}
Is there an easy way to do this?
Here is the general solution if you really only want the first key's value
Object firstKey = myHashMap.keySet().toArray()[0];
Object valueForFirstKey = myHashMap.get(firstKey);
You can iterate over keys by calling map.keySet(), or iterate over the entries by calling map.entrySet(). Iterating over entries will probably be faster.
for (Map.Entry<String, List<String>> entry : map.entrySet()) {
List<String> list = entry.getValue();
// Do things with the list
}
If you want to ensure that you iterate over the keys in the same order you inserted them then use a LinkedHashMap.
By the way, I'd recommend changing the declared type of the map to <String, List<String>>. Always best to declare types in terms of the interface rather than the implementation.
HashMaps are not ordered, unless you use a LinkedHashMap or SortedMap. In this case, you may want a LinkedHashMap. This will iterate in order of insertion (or in order of last access if you prefer). In this case, it would be
int index = 0;
for ( Map.Entry<String,ArrayList<String>> e : myHashMap.iterator().entrySet() ) {
String key = e.getKey();
ArrayList<String> val = e.getValue();
index++;
}
There is no direct get(index) in a map because it is an unordered list of key/value pairs. LinkedHashMap is a special case that keeps the order.
Kotlin HashMap Answer
You can get key by index. Then get value by key.
val item = HashMap<String, String>() // Dummy HashMap.
val keyByIndex = item.keys.elementAt(0) // Get key by index. I selected "0".
val valueOfElement = item.getValue(keyByIndex) // Get value.
You can do:
for(String key: hashMap.keySet()){
for(String value: hashMap.get(key)) {
// use the value here
}
}
This will iterate over every key, and then every value of the list associated with each key.
A solution is already selected. However, I post this solution for those who want to use an alternative approach:
// use LinkedHashMap if you want to read values from the hashmap in the same order as you put them into it
private ArrayList<String> getMapValueAt(LinkedHashMap<String, ArrayList<String>> hashMap, int index)
{
Map.Entry<String, ArrayList<String>> entry = (Map.Entry<String, ArrayList<String>>) hashMap.entrySet().toArray()[index];
return entry.getValue();
}
for (Object key : data.keySet()) {
String lKey = (String) key;
List<String> list = data.get(key);
}
I came across the same problem, read a couple of answers from different related questions and came up with my own class.
public class IndexableMap<K, V> extends HashMap<K, V> {
private LinkedList<K> keyList = new LinkedList<>();
#Override
public V put(K key, V value) {
if (!keyList.contains(key))
keyList.add(key);
return super.put(key, value);
}
#Override
public void putAll(Map<? extends K, ? extends V> m) {
for (Entry<? extends K, ? extends V> entry : m.entrySet()) {
put(entry.getKey(), entry.getValue());
}
}
#Override
public void clear() {
keyList.clear();
super.clear();
}
public List<K> getKeys() {
return keyList;
}
public int getKeyIndex(K key) {
return keyList.indexOf(key);
}
public K getKeyAt(int index) {
if (keyList.size() > index)
return keyList.get(index);
return null;
}
public V getValueAt(int index) {
K key = getKeyAt(index);
if (key != null)
return get(key);
return null;
}
}
Example (types are differing from OPs question just for clarity):
Map<String, Double> myMap = new IndexableMap<>();
List<String> keys = myMap.getKeys();
int keyIndex = myMap.getKeyIndex("keyString");
String key = myMap.getKeyAt(2);
Double value myMap.getValueAt(2);
Keep in mind that it does not override any of the complex methods, so you will need to do this on your own if you want to reliably access one of these.
Edit: I made a change to the putAll() method, because the old one had a rare chance to cause HashMap and LinkedList being in different states.
Try this:
myhashmap.entrySet()
.forEach{
println(it.getKey())
println(it.getValue())
}
or if you want by index
myhashmap.entrySet()[0].getKey()
myhashmap.entrySet()[0].getValue()
myhashmap.entrySet()[1].getKey()
myhashmap.entrySet()[1].getValue()
HashMaps don't keep your key/value pairs in a specific order. They are ordered based on the hash that each key's returns from its Object.hashCode() method. You can however iterate over the set of key/value pairs using an iterator with:
for (String key : hashmap.keySet())
{
for (list : hashmap.get(key))
{
//list.toString()
}
}
If you don't care about the actual key, a concise way to iterate over all the Map's values would be to use its values() method
Map<String, List<String>> myMap;
for ( List<String> stringList : myMap.values() ) {
for ( String myString : stringList ) {
// process the string here
}
}
The values() method is part of the Map interface and returns a Collection view of the values in the map.
You can use Kotlin extension function
fun LinkedHashMap<String, String>.getKeyByPosition(position: Int) =
this.keys.toTypedArray()[position]
fun LinkedHashMap<String, String>.getValueByPosition(position: Int) =
this.values.toTypedArray()[position]
You'll need to create multiple HashMaps like this for example
Map<String, String> fruitDetails = new HashMap();
fruitDetails.put("Mango", "Mango is a delicious fruit!");
fruitDetails.put("Guava" "Guava is a delicious fruit!");
fruitDetails.put("Pineapple", "Pineapple is a delicious fruit!");
Map<String, String> fruitDetails2 = new HashMap();
fruitDetails2.put("Orange", "Orange is a delicious fruit!");
fruitDetails2.put("Banana" "Banana is a delicious fruit!");
fruitDetails2.put("Apple", "Apple is a delicious fruit!");
// STEP 2: Create a numeric key based HashMap containing fruitDetails so we can access them by index
Map<Integer, Map<String, String>> hashMap = new HashMap();
hashMap.put(0, fruitDetails);
hashMap.put(1, fruitDetails2);
// Now we can successfully access the fruitDetails by index like this
String fruit1 = hashMap.get(0).get("Guava");
String fruit2 = hashMap.get(1).get("Apple");
System.out.println(fruit1); // outputs: Guava is a delicious fruit!
System.out.println(fruit2); // outputs: Apple is a delicious fruit!