java Get hashmap keys as integer array - java

I have a hashmap like this
public HashMap <String,People> valueHashMap = new Hashmap();
Here the key to my HashMap is time in seconds as string, ie I am adding value to hashmap like this
long timeSinceEpoch = System.currentTimeMillis()/1000;
valueHashMap.put(
Integer.toString((int)timeSinceEpoch)
, people_obj
);
Now I want to get all keys in the hashmap into an array list of integer.
ArrayList<Integer> intKeys = valueHashMap.keys()...
Is there any way to do that?

There is no direct way of converting a list of Strings to a list of Integers:
Either you need to redefine your valueHashMap like this:
public HashMap<Integer, People> valueHashMap = new HashMap<Integer, People>();
....
ArrayList<Integer> intKeys = new ArrayList<Integer>(valueHashMap.keySet());
Or you need to loop:
ArrayList<Integer> intKeys = new ArraList<Integer>();
for (String stringKey : valueHashMap.keySet())
intKeys.add(Integer.parseInt(stringKey);
I would advice you however to use the Long as key instead:
public HashMap<Long, People> valueHashMap = new HashMap<Long, People>();
then there would be no casting to int (and you can use (1) above with Long instead).

You can't cast a List of one type to a List of another type, so you have to iterate through the keys and parse each one.
for(String k : valueHashMap.keySet()) {
intKeys.add(Integer.valueOf(k));
}

You really have type problems. Why do you change the longs into Strings to store them in a map. Why not simply use Long, which needs less memory and is more descriptive. Then why use Integer.toString to transform a long into a String? By casting your long to an int, you risk loosing information by. Here's how the code should probably look like:
private Map<Long, People> valueHashMap = new Hashmap<Long, People>();
long timeSinceEpoch = System.currentTimeMillis()/1000;
valueHashMap.put(timeSinceEpoch, people_obj);
List<Long> longKeys = new ArrayList<Long>(valueHashMap.keySet());

You can use org.apache.commons.collections.Transformer class for that as follows.
List<Integer> intKeys = (List<Integer>)CollectionUtils.collect(valueHashMap.keySet(), new Transformer() {
#Override
public Object transform(Object key) {
return Integer.valueOf(key);
}
}, new ArrayList<Integer>());

Related

How to create a HashMap that would have String as key and the value would be another HashMap from one list of custom object?

I have a list of custom object,
public class Assignmentsdata {
String assignmentId;
String teacherId;
String groupName;
String sectionId;
String levelId;
String startTime;
}
ArrayList<Assignmentsdata> list = new ArrayList<>();
lets say there are 20 elements in that list.
Now I want to get the output which is a hashmap of startTime as a key and the Value would be a new HashMap of GroupID and a list of Assignments of those that had the same groupName.
OutPut Example
HashMap<startTime,HasMap<groupName,List> hashMap = new HashMap();
a little more insight about the problem: First I want to categorise based on startTime(Month) then i want to categorise based on groupName, Thanks in advance.
I have successfully categorised based on group name and created a map through below code:
for( int i = 0; i<assignmentsdataArrayList.size();i++ ){
if (hashMap.size()>0){
hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}else {
hashMap.put(assignmentsdataArrayList.get(i).getGroupName(),new ArrayList<Assignmentsdata>());
hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}
}
After that I am lost on how to categorise this hashmap based on the startDate and create a hashmap that would look like the above hashmap in the output heading.
your code may throw a NullPointerException at the first if branch
if (hashMap.size()>0)
{hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}
the map.size()>0 doesnt means the Value of GroupName has put a new ArrayList already.
the anwser of using loop should like this
Map<String, Map<String, List<Assignmentsdata>>> map = new HashMap<>();
for (Assignmentsdata assignmentsdata : list) {
if (!map.containsKey(assignmentsdata.getStartTime())) {
map.put(assignmentsdata.getStartTime(), new HashMap<>());
}
Map<String, List<Assignmentsdata>> startTimeMap = map.get(assignmentsdata.startTime);
if (!startTimeMap.containsKey(assignmentsdata.getGroupName())) {
startTimeMap.put(assignmentsdata.getGroupName(), new ArrayList<>());
}
startTimeMap.get(assignmentsdata.groupName).add(assignmentsdata);
}
or you could use the java stream().collect(Collectors.groupingBy()) api to get the result easily
Map<String, Map<String, List<Assignmentsdata>>> result = list.stream()
.collect(Collectors.groupingBy(Assignmentsdata::getStartTime,Collectors.groupingBy(Assignmentsdata::getGroupName)));
I am answering my own question as I solved it if anyone has a better answer please passed your answer aswell, ill accept another answer suitable and efficient answer.
for( int i = 0; i<assignmentsdataArrayList.size();i++ ){
if (hashMap.size()>0){
if (hashMap.get(assignmentsdataArrayList.get(i).getGroupName())==null){
hashMap.put(assignmentsdataArrayList.get(i).getGroupName(),new ArrayList<Assignmentsdata>());
hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}else{
hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}
}else {
hashMap.put(assignmentsdataArrayList.get(i).getGroupName(),new ArrayList<Assignmentsdata>());
hashMap.get(assignmentsdataArrayList.get(i).getGroupName()).add(assignmentsdataArrayList.get(i));
}
}
// above part is already in the question. the second part i looped through the hashMap then the list once again, and checking if list and map entry have same group name, then made the startdate key that indexed element from the list.
HashMap<String, Map.Entry<String, ArrayList<Assignmentsdata>>> hashMapHashMap = new HashMap<>();
for (var entry : hashMap.entrySet()){
for( int j = 0; j<assignmentsdataArrayList.size();j++ ){
if (assignmentsdataArrayList.get(j).getGroupName()==entry.getKey()){
hashMapHashMap.put(assignmentsdataArrayList.get(j).getStartTime(),entry);
}
}
hashMapHashMap.put(entry.getValue().get())
}

Is there a way to perform addition/subtraction with HashMap values in Java among Integer objects?

public static HashMap makeHashMap() {
HashMap<String, Integer> table = new HashMap<String, Integer>();
table.put("C", 1);
table.put("V", 2);
table.put("D", 3);
table.put("W", 4);
table.put("E", 5);
table.put("F", 6);
table.put("X", 7);
table.put("G", 8);
table.put("Y", 9);
table.put("A", 10);
table.put("Z", 11);
table.put("B", 12);
// System.out.print(table);
return table;
}
public static ArrayList<Object> makeArrayList(HashMap<String, Integer> table) {
Object[] keys = table.keySet().toArray();
ArrayList<Object> randomlyGeneratedNotes = new ArrayList<Object>();
for (int i = 0; i < 83; i++) {
Object key = keys[new Random().nextInt(keys.length)];
// System.out.println(key + " " + table.get(key));
randomlyGeneratedNotes.add(key);
}
System.out.println(randomlyGeneratedNotes);
return randomlyGeneratedNotes;
}
public static void pitchMovement(ArrayList<Object> randomlyGeneratedNotes, HashMap table) {
Iterator<String> keySetIterator = table.keySet().iterator();
String key = keySetIterator.next();
int first = table.get(key);
for (Object o : randomlyGeneratedNotes) {
//you want to grab the values of 2 neighboring keys
if (table.containsKey(o)) {
// System.out.println("true");
Object firstNote= table.get(key);
System.out.println(firstNote);
}
}
}
}
How can I perform addition/subtraction between my HashMap values? Or did I use an inappropriate data structure? I tried doing something my pitchMovement method, but the int first = table.get(key); line gives an error of incompatible types:
Object cannot be converted to int.
Not sure if this is a simple error or a more complex one.
I'd like to encourage you to put some learning effort into understanding generics and interfaces. Java will be friendly in its conversion between primitives and value types (like int and Integer), but plays dumb when dealing with objects of type Object. The problem you're encountering in multiple places is that you're needlessly letting your strongly typed values degrade to type Object.
I'd suggest the following changes:
Change public static HashMap makeHashMap() to public static HashMap<String,Integer>. Otherwise, you'll get back the equivalent of HashMap<Object,Object>, which you don't want.
In public static ArrayList<Object> makeArrayList(HashMap<String, Integer> table), you're extracting the String typed keys from HashMap, and then converting them to type Object when building your array. Don't change their type-- keep them as String. You may have been thrown by "toArray()" converting to an array of Object values. You can use this technique to preserve the type:
String[] keys=new String[table.size()];
keys=table.keySet().toArray(keys);
In doing so, you can easily change the signature of makeArrayList to return an ArrayList of type String:
public static ArrayList<String> makeArrayList(HashMap<String, Integer> table)
Your pitchMovement signature could be changed to:
public static void pitchMovement(ArrayList<String> randomlyGeneratedNotes,
HashMap<String,Integer> table)
Note that the specific error you encountered related to HashMap table being defined without generic parameters (which is equivalent to HashMap<Object,Object>).
When your types haven't been reduced to Object, then Java will use "auto-boxing" to automatically convert between your int and Integer types as needed. The following, for example, is valid.
Integer x=new Integer(5);
int y=10+x;
Integer z=x+y;
In sum, math operations will work as you'd expect without you having to cast and convert between primitives and their equivalent value types, no matter where you store them, but you must take efforts to keep those types preserved wherever you use them.
Try
Integer first = table.get(key);
as table is a map of String and Integer, you can get the value as Integer.
You can then convert your Integer variable to int.
You need to update your method signature with generic parameters:
public static void pitchMovement(ArrayList<Object> randomlyGeneratedNotes, HashMap<String, Integer> table)

key value pair implementation in java?

Is there something like a KeyValuePair in Java?
I have a Very long list of elements of the following class:
public class Foo {
int id;
Set<String> items;
}
which is stored here:
LinkedList<Foo> myList;
each time I search for a item, I iterate over the list and search for the Item, but this takes to much time.
I want to do something like this:
myList.get(123) => items of the Foo with id = 123
You can use Map in Java for that purpose. It will allow key, value pairs.
Map<Integer,Set<String>> map = new HashMap<Integer,Set<String>>();
Adding item to map
Set<String> set = new HashSet<String>();
set.add("ABC");
set.add("DEF");
map.put(123,set);
Getting item from map
map .get(123) will give Set<String> associated with id 123
Try some impelementation of java.util.Map.
More info: here
I think the MultiMap<Integer,String> is suitable in your case.
Guava MultiMap
Apache commons MultiMap
you would need a so called MultiMap, java dont has that by default, but you always can use a Map for that purpose.
Try using a HashMap<Integer, Set<String>>
import java.util.*;
class temp{
public static void main(String[] args){
Map<Integer,String> map = new HashMap<Integer,String>();
map.put(1,"anand");
map.put(2,"bindu");
map.put(3,"cirish");
System.out.println(1+" = "+map.get(1));
System.out.println(2+" = "+map.get(2));
System.out.println(3+" = "+map.get(3));
Map<String,Integer> map1 = new HashMap<String,Integer>();
map1.put("anand",1);
map1.put("bindu",2);
map1.put("cirish",3);
System.out.println("anand = "+map1.get("anand"));
System.out.println("bindu = "+map1.get("bindu"));
if(map1.get("cirish") != null){
System.out.println("cirish = "+map1.get("cirish"));
}
if(map1.get("dinesh") != null){
System.out.println("cirish = "+map1.get("dinesh"));
}
}
}

How to optimize the updating of values in an ArrayList<Integer>

I want to store all values of a certain variable in a dataset and the frequency for each of these values. To do so, I use an ArrayList<String> to store the values and an ArrayList<Integer> to store the frequencies (since I can't use int). The number of different values is unknown, that's why I use ArrayList and not Array.
Example (simplified) dataset:
a,b,c,d,b,d,a,c,b
The ArrayList<String> with values looks like: {a,b,c,d} and the ArrayList<Integer> with frequencies looks like: {2,3,2,2}.
To fill these ArrayLists I iterate over each record in the dataset, using the following code.
public void addObservation(String obs){
if(values.size() == 0){// first value
values.add(obs);
frequencies.add(new Integer(1));
return;//added
}else{
for(int i = 0; i<values.size();i++){
if(values.get(i).equals(obs)){
frequencies.set(i, new Integer((int)frequencies.get(i)+1));
return;//added
}
}
// only gets here if value of obs is not found
values.add(obs);
frequencies.add(new Integer(1));
}
}
However, since the datasets I will use this for can be very big, I want to optimize my code, and using frequencies.set(i, new Integer((int)frequencies.get(i)+1)); does not seem very efficient.
That brings me to my question; how can I optimize the updating of the Integer values in the ArrayList?
Use a HashMap<String,Integer>
Create the HashMap like so
HashMap<String,Integer> hm = new HashMap<String,Integer>();
Then your addObservation method will look like
public void addObservation(String obs) {
if( hm.contains(obs) )
hm.put( obs, hm.get(obs)+1 );
else
hm.put( obs, 1 );
}
I would use a HashMap or a Hashtable as tskzzy suggested. Depending on your needs I would also create an object that has the name, count as well as other metadata that you might need.
So the code would be something like:
Hashtable<String, FrequencyStatistics> statHash = new Hashtable<String, FrequencyStatistics>();
for (String value : values) {
if (statHash.get(value) == null) {
FrequencyStatistics newStat = new FrequencyStatistics(value);
statHash.set(value, newStat);
} else {
statHash.get(value).incrementCount();
}
}
Now, your FrequencyStatistics objects constructor would automatically set its inital count to 1, while the incrementCound() method would increment the count, and perform any other statistical calculations that you might require. This should also be more extensible in the future than storing a hash of the String with only its corresponding Integer.

Is there a way to get the value of a HashMap randomly in Java?

Is there a way to get the value of a HashMap randomly in Java?
This works:
Random generator = new Random();
Object[] values = myHashMap.values().toArray();
Object randomValue = values[generator.nextInt(values.length)];
If you want the random value to be a type other than an Object simply add a cast to the last line. So if myHashMap was declared as:
Map<Integer,String> myHashMap = new HashMap<Integer,String>();
The last line can be:
String randomValue = (String) values[generator.nextInt(value.length)];
The below doesn't work, Set.toArray() always returns an array of Objects, which can't be coerced into an array of Map.Entry.
Random generator = new Random();
Map.Entry[] entries = myHashMap.entrySet().toArray();
randomValue = entries[generator.nextInt(entries.length)].getValue();
Since the requirements only asks for a random value from the HashMap, here's the approach:
The HashMap has a values method which returns a Collection of the values in the map.
The Collection is used to create a List.
The size method is used to find the size of the List, which is used by the Random.nextInt method to get a random index of the List.
Finally, the value is retrieved from the List get method with the random index.
Implementation:
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("Hello", 10);
map.put("Answer", 42);
List<Integer> valuesList = new ArrayList<Integer>(map.values());
int randomIndex = new Random().nextInt(valuesList.size());
Integer randomValue = valuesList.get(randomIndex);
The nice part about this approach is that all the methods are generic -- there is no need for typecasting.
Should you need to draw futher values from the map without repeating any elements you can put the map into a List and then shuffle it.
List<Object> valuesList = new ArrayList<Object>(map.values());
Collections.shuffle( valuesList );
for ( Object obj : valuesList ) {
System.out.println( obj );
}
Generate a random number between 0 and the number of keys in your HashMap. Get the key at the random number. Get the value from that key.
Pseudocode:
int n = random(map.keys().length());
String key = map.keys().at(n);
Object value = map.at(key);
If it's hard to implement this in Java, then you could create and array from this code using the toArray() function in Set.
Object[] values = map.values().toArray(new Object[map.size()]);
Object random_value = values[random(values.length)];
I'm not really sure how to do the random number.
Converting it to an array and then getting the value is too slow when its in the hot path.
so get the set (either the key or keyvalue set) and do something like:
public class SetUtility {
public static<Type> Type getRandomElementFromSet(final Set<Type> set, Random random) {
final int index = random.nextInt(set.size());
Iterator<Type> iterator = set.iterator();
for( int i = 0; i < index-1; i++ ) {
iterator.next();
}
return iterator.next();
}
A good answer depends slightly on the circumstances, in particular how often you need to get a random key for a given map (N.B. the technique is essentially the same whether you take key or value).
If you need various random keys
from a given map, without the map
changing in between getting the
random keys, then use the random
sampling method as you iterate
through the key set. Effectively what
you do is iterate over the set
returned by keySet(), and on each
item calculate the probability of
wanting to take that key, given how
many you will need overall and the
number you've taken so far. Then
generate a random number and see if
that number is lower than the
probability. (N.B. This method will always work, even if you only need 1 key; it's just not necessarily the most efficient way in that case.)
The keys in a HashMap are effectively
in pseudo-random order already. In an
extreme case where you will only
ever need one random key for a
given possible map, you could even just
pull out the first element of the
keySet().
In other cases (where you either
need multiple possible random keys
for a given possible map, or the map
will change between you taking random
keys), you essentially have to
create or maintain an array/list of the keys from which you select a
random key.
If you are using Java 8, findAny function in a pretty solution:
MyEntityClass myRandomlyPickedObject = myHashMap.values().stream().findAny();
i really don't know why you want to do this... but if it helps, i've created a RandomMap that automatically randomizes the values when you call values(), then the following runnable demo application might do the job...
package random;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
public class Main {
public static void main(String[] args) {
Map hashMap = makeHashMap();
// you can make any Map random by making them a RandomMap
// better if you can just create the Map as a RandomMap instead of HashMap
Map randomMap = new RandomMap(hashMap);
// just call values() and iterate through them, they will be random
Iterator iter = randomMap.values().iterator();
while (iter.hasNext()) {
String value = (String) iter.next();
System.out.println(value);
}
}
private static Map makeHashMap() {
Map retVal;
// HashMap is not ordered, and not exactly random (read the javadocs)
retVal = new HashMap();
// TreeMap sorts your map based on Comparable of keys
retVal = new TreeMap();
// RandomMap - a map that returns stuff randomly
// use this, don't have to create RandomMap after function returns
// retVal = new HashMap();
for (int i = 0; i < 20; i++) {
retVal.put("key" + i, "value" + i);
}
return retVal;
}
}
/**
* An implementation of Map that shuffles the Collection returned by values().
* Similar approach can be applied to its entrySet() and keySet() methods.
*/
class RandomMap extends HashMap {
public RandomMap() {
super();
}
public RandomMap(Map map) {
super(map);
}
/**
* Randomize the values on every call to values()
*
* #return randomized Collection
*/
#Override
public Collection values() {
List randomList = new ArrayList(super.values());
Collections.shuffle(randomList);
return randomList;
}
}
Here is an example how to use the arrays approach described by Peter Stuifzand, also through the values()-method:
// Populate the map
// ...
Object[] keys = map.keySet().toArray();
Object[] values = map.values().toArray();
Random rand = new Random();
// Get random key (and value, as an example)
String randKey = keys[ rand.nextInt(keys.length) ];
String randValue = values[ rand.nextInt(values.length) ];
// Use the random key
System.out.println( map.get(randKey) );
Usually you do not really want a random value but rather just any value, and then it's nice doing this:
Object selectedObj = null;
for (Object obj : map.values()) {
selectedObj = obj;
break;
}
I wrote a utility to retrieve a random entry, key, or value from a map, entry set, or iterator.
Since you cannot and should not be able to figure out the size of an iterator (Guava can do this) you will have to overload the randEntry() method to accept a size which should be the length of the entries.
package util;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
public class MapUtils {
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>() {
private static final long serialVersionUID = 1L;
{
put("Foo", 1);
put("Bar", 2);
put("Baz", 3);
}
};
System.out.println(randEntryValue(map));
}
static <K, V> Entry<K, V> randEntry(Iterator<Entry<K, V>> it, int count) {
int index = (int) (Math.random() * count);
while (index > 0 && it.hasNext()) {
it.next();
index--;
}
return it.next();
}
static <K, V> Entry<K, V> randEntry(Set<Entry<K, V>> entries) {
return randEntry(entries.iterator(), entries.size());
}
static <K, V> Entry<K, V> randEntry(Map<K, V> map) {
return randEntry(map.entrySet());
}
static <K, V> K randEntryKey(Map<K, V> map) {
return randEntry(map).getKey();
}
static <K, V> V randEntryValue(Map<K, V> map) {
return randEntry(map).getValue();
}
}
If you are fine with O(n) time complexity you can use methods like values() or values().toArray() but if you look for a constant O(1) getRandom() operation one great alternative is to use a custom data structure. ArrayList and HashMap can be combined to attain O(1) time for insert(), remove() and getRandom(). Here is an example implementation:
class RandomizedSet {
List<Integer> nums = new ArrayList<>();
Map<Integer, Integer> valToIdx = new HashMap<>();
Random rand = new Random();
public RandomizedSet() { }
/**
* Inserts a value to the set. Returns true if the set did not already contain
* the specified element.
*/
public boolean insert(int val) {
if (!valToIdx.containsKey(val)) {
valToIdx.put(val, nums.size());
nums.add(val);
return true;
}
return false;
}
/**
* Removes a value from the set. Returns true if the set contained the specified
* element.
*/
public boolean remove(int val) {
if (valToIdx.containsKey(val)) {
int idx = valToIdx.get(val);
int lastVal = nums.get(nums.size() - 1);
nums.set(idx, lastVal);
valToIdx.put(lastVal, idx);
nums.remove(nums.size() - 1);
valToIdx.remove(val);
return true;
}
return false;
}
/** Get a random element from the set. */
public int getRandom() {
return nums.get(rand.nextInt(nums.size()));
}
}
The idea comes from this problem from leetcode.com.
It seems that all other high voted answers iterate over all the elements. Here, at least, not all elements must be iterated over:
Random generator = new Random();
return myHashMap.values().stream()
.skip(random.nextInt(myHashMap.size()))
.findFirst().get();
It depends on what your key is - the nature of a hashmap doesn't allow for this to happen easily.
The way I can think of off the top of my head is to select a random number between 1 and the size of the hashmap, and then start iterating over it, maintaining a count as you go - when count is equal to that random number you chose, that is your random element.

Categories

Resources