I am trying to enhance the code on a JAVA project.
an old method was to build a hashmap manually like this - essentially taking parameters from a form a batch of String numbers --
So ConsiderateOfOtherPeoplesFeelings -- would be like "22"
Map<String, Integer> sDMap = new HashMap<String, Integer>();
sDMap.put("ConsiderateOfOtherPeoplesFeelings", BasicUtils.strToIntConversion(ConsiderateOfOtherPeoplesFeelings));
sDMap.put("RestlessOveractiveCannotStayStillForLong", BasicUtils.strToIntConversion(RestlessOveractiveCannotStayStillForLong));
so the map would populate ideally like this
OLD MAP.........{StealsFromHomeSchoolOrElsewhere=2, HasAtLeastOneGoodFriend=0}
-- I am trying to create this same map - with a hashMapBuilder function
public static Map<String, Integer> hashMapBuilder (String[] array){
Map<String, Integer> map = new HashMap<String, Integer>();
for( String element : array ) {
map.put(element.toString(), BasicUtils.strToIntConversion(element));
}
return map;
}
although the response is not correct.
NEW MAP.........{0=0, 1=1, 2=2}
the strToIntConversion looks like this - as it will take a null/string value and convert it into an Integer
public static Integer strToIntConversion(String str){
int number = 0;
try {
if(str != null){
number = Integer.parseInt(str);
}
}
catch (NumberFormatException e) {
number = 0;
}
return number;
}
when I do this it returns {0=0, 1=1, 2=2} --
String[] myStrings = {ConsiderateOfOtherPeoplesFeelings, RestlessOveractiveCannotStayStillForLong, OftenComplainsOfHeadachesStomachachesOrSickness};
Map<String, Integer> newMap = BasicUtils.hashMapBuilder(myStrings);
System.out.println("NEW MAP........."+ newMap);
In the old code you have:
sDMap.put("ConsiderateOfOtherPeoplesFeelings", BasicUtils.strToIntConversion(ConsiderateOfOtherPeoplesFeelings));
This is a string: "ConsiderateOfOtherPeoplesFeelings"
And this is a variable probably holding the numerical valu: ConsiderateOfOtherPeoplesFeelings
so you should be using those variables as well
You could potentially use annotations to make this happen
class MyData {
#RobSearchable String ConsiderateOfOtherPeoplesFeelings;
#RobSearchable String RestlessOveractiveCannotStayStillForLong;
#RobSearchable String StealsFromHomeSchoolOrElsewhere;
}
Later, you could do this
public static Map<String, Integer> hashMapBuilder(MyData data){
Map<String, Integer> map = new HashMap<String, Integer>();
for(Field f : data.getClass().getDeclaredFields()) {
if(f.getAnnotation(RobSearchable.class) != null) {
String element = f.get(data).toString();
map.put(element.toString(), BasicUtils.strToIntConversion(element));
}
}
return map;
}
Now, as you continue to add fields to your data, they will all automatically show up in the map, as long as you annotate them properly.
Related
Is there a code for finding a specific value in a hashmap?
I want to use a for loop to convert values in a hashmap into an int.
for (int i = 0; i < items; i++) {
cost = Integer.parseInt(myHashmap);
}
can I even use .parseInt on a hashmap or is there another way to convert a place in a hashmap into a int?
Like String[3] is there a code to find a specific place in a hashmap?
To iterate over all values of a map, use the values method:
Map<Long, String> map = ...;
for (final String value = map.values()) {
System.out.println(value);
}
To find a specific value, iterate all values, check against your predicate and return if found:
String findValue(final Map<Long, String> map, final Predicate<String> condition) {
for (final String value = map.values()) {
if (condition.test(value)) {
return value;
}
}
return null;
}
To find the key for a given value, iterate the entry set of the map:
Long findKey(final Map<Long, String> map, final String value) {
for (final Map.Entry<Long, String> entry = map.entrySet()) {
if (Objects.equals(entry.getValue(), value)) {
return entry.getKey();
}
}
return null;
}
Of course, once you have a value (or a key), you can use it any way you like. That includes passing it as argument to Integer.parseInt.
myHashmap.values() will return all the values of the Map. Integer.parseInt(value) parses the String argument as a signed decimal integer object.
public static void main(String[] args) {
Map<String, String> myHashmap = new HashMap<>();
myHashmap.put("A", "10");
myHashmap.put("B", "20");
myHashmap.put("C", "30");
myHashmap.values().forEach(value -> {
System.out.println(Integer.parseInt(value));
// Rest of the logic
});
}
I'm making a custom irritator to use in a SortedMap with keys being strings and the values being a count of how many times that string has been read.
When I run it, I get this error:
java.lang.ClassCastException: java.lang.String cannot be cast to java.util.Map$Entry
at comp2402a1.Part8$1.compare(Part8.java:21)
I can't seem to figure out why I'm getting this casting error. Any help and insight anyone could provide would be really appreciated.
Here is my code:
public static void doIt(BufferedReader r, PrintWriter w) throws IOException {
//Custom comparator
Comparator<Map.Entry<String, Integer>> mapCompare = new Comparator<Map.Entry<String, Integer>>(){
#Override
public int compare(Map.Entry<String, Integer> o1, Map.Entry<String, Integer> o2) {
if (o1.getValue()-o2.getValue() != 0){
return o1.getValue()-o2.getValue();
} else {
return o1.getKey().compareTo(o2.getKey());
}
}
};
//Read lines into a HashMap & count instance #s
HashMap<String, Integer> hMap = new HashMap();
for (String line = r.readLine(); line != null; line = r.readLine()) {
if (hMap.get(line)==null) {
hMap.put(line,1);
w.println("1");
} else {
hMap.put(line, hMap.get(line)+1);
}
}
//Put objects into sorted map w/custom sort and output
SortedMap<String, Integer> sMap = new TreeMap(mapCompare);
sMap.putAll(hMap);
for (Map.Entry<String, Integer> e : sMap.entrySet()){
w.println(e.getKey());
}
}
The error was appearing because I was creating a comparator of type Comparator<Map.Entry<String, Integer>> instead of Comparator<String>.
I fixed it by first creating calling Map.entrySet() on my HashMap, putting that into a list, sorting it, then basing my SortedMap off of that.
My assignment is to write code that swaps the keys for the values of a map (with non 1:1) ratio, and I thought to create a TreeMap. So far I have:
public static Map<String, Set<String>> reverseMapping(Map<String, String> mapping) {
TreeMap <String, String> temp = (TreeMap<String, String>) mapping;
while (temp.pollFirstEntry() !=null ){
Map.Entry<String, String> iter=temp.pollFirstEntry();
String newKey = iter.get(iter.firstKey());
}
but it's saying that first.Key() is undefined for map.entry and suggests I cast iter. but that just makes things worse.
How can I achieve my goal of breaking the map entry down into its keys and values in a new set and string, respectively? Is this possible using the starting point I have, or at all?
As per your comments, what you want to know is how to iterate over each entries of a map.
Let me explain you how with a simple snippet :
for(Map.Entry<String, String> entry : temp.entrySet())
{
String key = entry.getKey();
String value = entry.getValue();
}
I'm pretty sure you can solve your issue now.
This will give you the reverse of a map.
import java.util.*;
public class HelloWorld{
public static void main(String []args){
System.out.println("Hello World");
TreeMap<String, String> tm1 =new TreeMap<String, String>();
tm1.put("Hello" , "Me");
tm1.put("Bye", "Jim");
TreeMap<String , String > reverse = reverse(tm1);
System.out.println(reverse);
}
public static TreeMap<String , String > reverse(TreeMap<String, String> tm1){
TreeMap<String , String > reverse =new TreeMap<String, String>();
for(String s : tm1.keySet())
{
String v= tm1.get(s);
reverse.put(v,s);
}
return reverse;
}
}
I want to create methods which return the amount of same first names and last names, but when i try to test and compile code i get as output 1 , 1 , and this is not true. because there is 10 same names and 10 same last names.
public class Solution
{
public static void main(String[] args)
{
HashMap<String, String> map = createMap();
System.out.println(getCountTheSameFirstName(map, "test"));
System.out.println(getCountTheSameLastName(map, "test"));
}
public static HashMap<String, String> createMap()
{
HashMap<String, String> odin = new HashMap<String, String>();
odin.put("test","test");
odin.put("test","test");
odin.put("test","test");
odin.put("test","test");
odin.put("test","test");
odin.put("test","test");
odin.put("test","test");
odin.put("test","test");
odin.put("test","test");
odin.put("test","test");
return odin;
}
public static int getCountTheSameFirstName(HashMap<String, String> map, String name)
{
int count = 0;
for(Map.Entry<String, String> lol : map.entrySet()){
String value = lol.getValue();
if(name.equals(value)){
count++;
}
}
return count;
}
public static int getCountTheSameLastName(HashMap<String, String> map, String familiy)
{
int count=0;
for (Map.Entry<String,String> pair : map.entrySet())
{
String key = pair.getKey();
if (familiy.equals(key))
{
count++;
}
}
return count;
}
}
Please consult the HashMap-API, it is correct by definition: "Associates the specified value with the specified key in this map. If the map previously contained a mapping for the key, the old value is replaced." (http://docs.oracle.com/javase/6/docs/api/java/util/HashMap.html#put(K, V))
Sorry!! if you are not use duplicate key then you have to have get the output 10 & 0
Your code: Just I have changed the key and got the output 10 & 0:
public class Solution
{
public static void main(String[] args)
{
HashMap<String, String> map = createMap();
System.out.println(getCountTheSameFirstName(map, "test"));
System.out.println(getCountTheSameLastName(map, "test"));
}
public static HashMap<String, String> createMap()
{
HashMap<String, String> odin = new HashMap<String, String>();
odin.put("0","test");
odin.put("1","test");
odin.put("2","test");
odin.put("3","test");
odin.put("4","test");
odin.put("5","test");
odin.put("6","test");
odin.put("7","test");
odin.put("8","test");
odin.put("9","test");
return odin;
}
public static int getCountTheSameFirstName(HashMap<String, String> map, String name)
{
int count = 0;
for(Map.Entry<String, String> lol : map.entrySet()){
String value = lol.getValue();
if(name.equals(value)){
count++;
}
}
return count;
}
public static int getCountTheSameLastName(HashMap<String, String> map, String familiy)
{
int count=0;
for (Map.Entry<String,String> pair : map.entrySet())
{
String key = pair.getKey();
if (familiy.equals(key))
{
count++;
}
}
return count;
}
}
You are inserting the same key 10 times. The first put works, but each subsequent put replaces the old key/value mapping with the same mapping. The end result is that there's only one key/value pair in the Map, so that's why you get 1 as output.
In short: Your method works as HashMap is designed - you force put to HashMap with same key and first time add value to map, and any other time you just change value of this element because it has same key.
Description:
You have this situation - You are created HashMap like that:
HashMap<String, String> odin = new HashMap<String, String>();
There is first string key and second string value. When you adding value with line:
odin.put("test","test");
You are set value test for key test.
If you repeat that, you will change old element with key test with new element with key test
This results is that entered value is replaced.
Instead of this, you have to put in HashMap something else (array for example) with unique key. In this case you can have 10 inputs with same values.
Here is example of this HashMap:
HashMap<String, String[]> odin = new HashMap<String, String[]>();
In that case you have to provide string key and array of strings which contains values (first names and last names from your question).
I need create inverse map - select unique values and for them find keys.
Seems that only way is to iterate all key/value pairs, because entrySet returns set of <key,value> so value not unique?
The values in a map may not be unique. But if they are (in your case) you can do as you wrote in your question and create a generic method to convert it:
private static <V, K> Map<V, K> invert(Map<K, V> map) {
Map<V, K> inv = new HashMap<V, K>();
for (Entry<K, V> entry : map.entrySet())
inv.put(entry.getValue(), entry.getKey());
return inv;
}
Java 8:
public static <V, K> Map<V, K> invert(Map<K, V> map) {
return map.entrySet()
.stream()
.collect(Collectors.toMap(Entry::getValue, Entry::getKey));
}
Example of usage:
public static void main(String[] args) {
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("Hello", 0);
map.put("World!", 1);
Map<Integer, String> inv = invert(map);
System.out.println(inv); // outputs something like "{0=Hello, 1=World!}"
}
Side note: the put(.., ..) method will return the the "old" value for a key. If it is not null you may throw a new IllegalArgumentException("Map values must be unique") or something like that.
Take a look at Google Guava BiMap.
Example usage
Map<Integer, String> map = new HashMap<>();
map.put(1, "one");
map.put(2, "two");
Map<String, Integer> inverted = HashBiMap.create(map).inverse();
To get an inverted form of a given map in java 8:
public static <K, V> Map<V, K> inverseMap(Map<K, V> sourceMap) {
return sourceMap.entrySet().stream().collect(
Collectors.toMap(Entry::getValue, Entry::getKey,
(a, b) -> a) //if sourceMap has duplicate values, keep only first
);
}
Example usage
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "one");
map.put(2, "two");
Map<String, Integer> inverted = inverseMap(map);
Seems that only way is to iterate all key/value pairs, because entrySet returns set of so value not unique?
It's one way at least. Here's an example:
Map<Integer, String> map = new HashMap<Integer, String>();
map.put(1, "one");
map.put(2, "two");
Map<String, Integer> inverted = new HashMap<String, Integer>();
for (Integer i : map.keySet())
inverted.put(map.get(i), i);
In case of non-unique values, this algorithm will map the last value found to it's key. (Since the iteration order is undefined for most maps, this should be as good as any solution.)
If you really do want to keep the first value found for each key, you could change it to
if (!inverted.containsKey(map.get(i)))
inverted.put(map.get(i), i);
I would give another approach to this problem giving an extra dimension:
duplicate values in EntrySet.
public static void main(String[] args) {
HashMap<Integer, String> s = new HashMap<Integer, String>();
s.put(1, "Value1");
s.put(2, "Value2");
s.put(3, "Value2");
s.put(4, "Value1");
/*
* swap goes here
*/
HashMap<String,List<Integer>> newMap = new HashMap<String, List<Integer>>();
for (Map.Entry<Integer, String> en : s.entrySet()) {
System.out.println(en.getKey() + " " + en.getValue());
if(newMap.containsKey(en.getValue())){
newMap.get(en.getValue()).add(en.getKey());
} else {
List<Integer> tmpList = new ArrayList<Integer>();
tmpList.add(en.getKey());
newMap.put(en.getValue(), tmpList);
}
}
for(Map.Entry<String, List<Integer>> entry: newMap.entrySet()){
System.out.println(entry.getKey() + " " + entry.getValue());
}
}
T result will be that:
1 Value1 2 Value2 3 Value2 4 Value1 Value1 [1, 4] Value2 [2, 3]
Apache Commons Collections also provides a BidiMap interface for bi-directional maps, along with several implementations.
BidiMap JavaDoc
If your values duplicate and you need to store keys in list you can go with
val invertedMap = originalMap.entrySet().stream()
.collect(Collectors.groupingBy(
Map.Entry::getValue,
Collectors.mapping(Map.Entry::getKey, Collectors.toList()))
);
You have to assume that values may be identical, since the Map contract allows it.
In my opinion the best solution lies in using a wrapper. It will contain the original value, and add an id. Its hashCode() function will rely on the id, and you provide a Getter for the original value.
Code would be something like this:
public class MapKey
{
/**
* A new ID to differentiate equal values
*/
private int _id;
/**
* The original value now used as key
*/
private String _originalValue;
public MapKey(String originalValue)
{
_originalValue = originalValue;
//assuming some method for generating ids...
_id = getNextId();
}
public String getOriginalValue()
{
return _originalValue;
}
#Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + _id;
return result;
}
#Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
MapKey other = (MapKey) obj;
if (_id != other._id)
return false;
return true;
}
#Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append("MapKey value is ");
sb.append(_originalValue);
sb.append(" with ID number ");
sb.append(_id);
return sb.toString();
}
Inverting the map would be something like this:
public Map <MapKey, Integer> invertMap(Map <Integer, String> map)
{
Map <MapKey, Integer> invertedMap = new HashMap <MapKey, Integer>();
Iterator<Entry<Integer, String>> it = map.entrySet().iterator();
while(it.hasNext())
{
//getting the old values (to be reversed)
Entry<Integer, String> entry = it.next();
Integer oldKey = entry.getKey();
String oldValue = entry.getValue();
//creating the new MapKey
MapKey newMapKey = new MapKey(oldValue);
invertedMap.put(newMapKey, oldKey);
}
return invertedMap;
}
Printing the values something like this:
for(MapKey key : invertedMap.keySet())
{
System.out.println(key.toString() + " has a new value of " + invertedMap.get(key));
}
None of this code is tested, but I believe it's the best solution since it makes use of OO inheritance design instead of "c" style checks and allows you to display all the original keys and values.
With Guava
Multimaps.transformValues(Multimaps.index(map.entrySet(), Map.Entry::getValue),
Map.Entry::getKey)
You'll get a multimap (basically a map of lists) in return.