This question already has answers here:
Java Hashmap: How to get key from value?
(39 answers)
Closed 5 years ago.
I want to get the key of a HashMap using the value.
hashmap = new HashMap<String, Object>();
haspmap.put("one", 100);
haspmap.put("two", 200);
Which means i want a function that will take the value 100 and will return the string one.
It seems that there are a lot of questions here asking the same thing but they don't work for me.
Maybe because i am new with java.
How to do it?
The put method in HashMap is defined like this:
Object put(Object key, Object value)
key is the first parameter, so in your put, "one" is the key. You can't easily look up by value in a HashMap, if you really want to do that, it would be a linear search done by calling entrySet(), like this:
for (Map.Entry<Object, Object> e : hashmap.entrySet()) {
Object key = e.getKey();
Object value = e.getValue();
}
However, that's O(n) and kind of defeats the purpose of using a HashMap unless you only need to do it rarely. If you really want to be able to look up by key or value frequently, core Java doesn't have anything for you, but something like BiMap from the Google Collections is what you want.
We can get KEY from VALUE. Below is a sample code_
public class Main {
public static void main(String[] args) {
Map map = new HashMap();
map.put("key_1","one");
map.put("key_2","two");
map.put("key_3","three");
map.put("key_4","four");
System.out.println(getKeyFromValue(map,"four"));
}
public static Object getKeyFromValue(Map hm, Object value) {
for (Object o : hm.keySet()) {
if (hm.get(o).equals(value)) {
return o;
}
}
return null;
}
}
I hope this will help everyone.
If you need only that, simply use put(100, "one"). Note that the key is the first argument, and the value is the 2nd.
If you need to be able to get by both the key and the value, use BiMap (from guava)
You have it reversed. The 100 should be the first parameter (it's the key) and the "one" should be the second parameter (it's the value).
Read the javadoc for HashMap and that might help you: HashMap
To get the value, use hashmap.get(100).
You mixed the keys and the values.
Hashmap <Integer,String> hashmap = new HashMap<Integer, String>();
hashmap.put(100, "one");
hashmap.put(200, "two");
Afterwards a
hashmap.get(100);
will give you "one"
if you what to obtain "ONE" by giving in 100 then
initialize hash map by
hashmap = new HashMap<Object,String>();
haspmap.put(100,"one");
and retrieve value by
hashMap.get(100)
hope that helps.
public class Class1 {
private String extref="MY";
public String getExtref() {
return extref;
}
public String setExtref(String extref) {
return this.extref = extref;
}
public static void main(String[] args) {
Class1 obj=new Class1();
String value=obj.setExtref("AFF");
int returnedValue=getMethod(value);
System.out.println(returnedValue);
}
/**
* #param value
* #return
*/
private static int getMethod(String value) {
HashMap<Integer, String> hashmap1 = new HashMap<Integer, String>();
hashmap1.put(1,"MY");
hashmap1.put(2,"AFF");
if (hashmap1.containsValue(value))
{
for (Map.Entry<Integer,String> e : hashmap1.entrySet()) {
Integer key = e.getKey();
Object value2 = e.getValue();
if ((value2.toString()).equalsIgnoreCase(value))
{
return key;
}
}
}
return 0;
}
}
If you are not bound to use Hashmap, I would advise to use pair< T,T >.
The individual elements can be accessed by first and second calls.
Have a look at this http://www.cplusplus.com/reference/utility/pair/
I used it here : http://codeforces.com/contest/507/submission/9531943
Related
I am trying to create a method that, when given a key and a value, can access the map via the key and then either add or replace that specific value.
My Hash Map is created like so:
public Band(){
musicians = new HashMap<>();
}
And I can add new entries like so, with band acting as the key:
public void addMapEntry(String band, String name, String instrument, int experience){
musicians.put(band, new Musician(name, instrument, experience));
}
My new method header look like this:
public void addValue(){ }
I have tried using the put method but I can't get it work as I'd like.
I have also tried iterating through the map, but I've only ever used that method to return map objects in a list, whereas I don't want to return anything in this method. I want to be able to send it two arguments (the key and the value) and have it only replace that specific value.
I hope I have been clear in my explanation.
Java Map is single value for each key.
If you need multiple values for a single key, you should make the type a collection of the appropriate type and add your own logic for adding a new value. Your Band class should have methods to add/remove a Musician and handle the details in the private implementation.
public class Band {
private Map<String, List<Musician>> members = new HashMap<String, List<Musician>>();
public void addMusician(String key, Musician musician) {
if (this.members.containsKey(key) {
List<Musician> musicians = this.members.get(key);
if (musician != null) {
musicians.add(musician);
this.members.put(key, musicians);
}
}
}
public void removeMusician(String key, Musician musician) {
// should be clear enough from the add method.
}
}
I think the most suitable for you is to use Guava Multimap
ListMultimap<String, String> musicianMap = ArrayListMultimap.create();
Then add as many musicians to your band
musicianMap.put("Beatles", new Musician("Jhon Lennon"));
musicianMap.put("Beatles", new Musician("Paul McCartney"));
musicianMap.put("Beatles", new Musician("Ringo Starr"));
musicianMap.put("Beatles", new Musician("George Harrison"));
And you can pull them all using just key.
musicianMap.get("Beatles")
This will return a list of ["John Lenon", "Paul McCartney", "Ringo Starr"] of course these will objects of class Musician.
I am creating a function that loops through a string, separates it by comma and then takes the key from the second item in the array and the value from the 1st after splitting the string.
I then want to place these values in a map. This works perfectly, however if i have two strings with the same key it doesn't add the value up it just replaces it.
For example if my string was
123,totti 100,roma, 100,totti
I would want
totti 223
roma 100
Here is my code
private void processCallLogs(String[] splitCalls) {
for (String individualCall : splitCalls) {
int duration = 0;
String[] singleCall = individualCall.split(",");
duration += DurationParser.returnDuration(singleCall[0]);
this.cost += CalculateCost.calculateCostPerCall(singleDuration);
if (totalCallDurations.containsKey(singleCall[1])) {
totalCallDurations.put(singleCall[1], singleDuration);
} else {
totalCallDurations.put(singleCall[1], duration);
}
}
}
You can replace the if with something like this:
if (totalCallDurations.containsKey(singleCall[1])) {
duration += totalCallDurations.get(singleCall[1]);
}
totalCallDurations.put(singleCall[1], duration);
Create a map and update the value if the key is present
public static void main(String[] args) {
myMap = new HashMap<>();
// 123,totti 100,roma, 100,totti
addToMap("totti", 123);
addToMap("roma", 100);
addToMap("totti", 100);
System.out.println(myMap);
}
private static void addToMap(String string, int i) {
int t = i;
if (myMap.get(string) != null) {
t += myMap.get(string);
}
myMap.put(string, t);
}
If you're using Java 8, you can do this easily with the Map.merge() method:
totalCallDurations.merge(singleCall[1], duration, Integer::sum);
If you want to make a map that will add the values together instead of replacing, I would recommend extending the Map type to make your own map. Since Map is very abstract. I would extend HashMap. (I suggest this both for code style and because it will make your code more extendable).
public class AdderMap extends HashMap<String, Integer> { // This extends the HashMap class
public Integer get(String key) { // This overrides the Map::get method
if(super.containsKey(key)) return super.get(key); // If the key-value pairing exists, return the value
else return 0; // If it doesn't exist, return 0
}
public Integer put(String key, Integer value) { // This overrides the Map::put method
Integer old_value = this.get(key); // Get the former value of the key-value pairing (which is 0 if it doesn't exist)
super.put(key, old_value + value); // Add the new value to the former value and replace the key-value pairing (this behaves normally when the former value didn't exist)
return old_value; // As per the documentation, Map::put will return the old value of the key-value pairing
}
}
Now, when you initialize your map, make it an AdderMap. Then, you can just use put(String, Integer) and it will add it together.
The advantage of this solution is that it helps with keeping your code clean and it allows you to use this type of map again in the future without needing separate code in your main code. The disadvantage is that it requires another class, and having too many classes can become cluttered.
This question already has answers here:
Sort a Map<Key, Value> by values
(64 answers)
Closed 8 years ago.
I saw this thread sorting a List of Map<String, String> and I know mine could sound a duplicate, but it is slight differen.
My example is:
List<Map<String, String>> myList = new ArrayList<Map<String, String>>();
...
for(MyClass1 c1 : c1)
{
...
for(MyClass2 c2 : c12)
{
SimpleBindings myBindindings= new SimpleBindings();
myBindindings.put(c1.getName(), c2.getName());
myList.add(myBindindings);
}
}
...
Concretely I can have
{
(John, Mike)
(John, Jack)
(Sam, Jack)
(Gloria, Anna)
(Jane, Carla)
...
}
and would like that my list is sorted by the maps key:
{
(Gloria, Anna)
(Jane, Carla)
(John, Mike)
(John, Jack)
(Sam, Jack)
...
}
Are you sure that
List<Map<String, String>>
is the approriate data type you want?
To me it looks like you are in fact looking simplify for
TreeMap<String, String>
i.e. a sorted map key -> value?
Or do you mean to use a List<StringPair> (for that, please choose a more appropriate name than StringPair, and implement that class to your needs)? I have the impression that in lack of an obvious Pair<String, String> class in Java you have been abusing SimpleBinding as a pair class. The proper way to have pairs in Java is to implement a new class, with a proper class name - "pair" is technical, not semantic.
You could also do
List<String[]>
and implement a Comparator<String[]> for sorting. But that doesn't save you any work over implementing a NamePair class and making it comparable yourself.
You need to implement Comparator to accomplish this...
Collections.sort(myList, new Comparator<ObjectBeingCompared>() {
#Override
public int compare(ObjectBeingCompared obj1, ObjectBeingCompared obj2) {
//Of course you will want to return 1, 0, -1 based on whatever you like
//this is just a simple example
//return 1 if obj1 should be ordered first
//return 0 if obj1 and obj2 are the same
//return -1 if obj1 should be ordered after obj2
return obj1.compareTo(obj2);
}
});
The HashMap data structure is used to allow access to its elements in O(1) time.
Because it is a container of data its pool or keys can vary in time. This mean that you can not assure in long therm an order for list of maps.
In your example you match two Strings and create Pair of data called SimpleBindings.
In case of your simple example you should not use Map<String,String> data structure to represent a Pair of data.
If you SimpleBindings really consist of two string, everything you must do is only implement a Comparable in SimpleBindings class like this:
class SimpleBinding implements Comparable<SimpleBinding> {
private final String key;
private final String value;
public SimpleBinding(String key, String value) {
Objects.nonNull(key);
Objects.nonNull(value);
this.key = key;
this.value = value;
}
#Override
public int compareTo(SimpleBinding that) {
return this.key.compareTo(that.key);
}
}
And the you just use the Collections.sort(bindings ) to have sorted result.
In case you do not have access to the class you should use the Comparator interface like this
enum SimpleBindingComparator implements Comparator<SimpleBinding> {
DEFUALT {
#Override
public int compare(SimpleBinding fist, SimpleBinding second) {
return fist.key.compareTo(second.key);
}
};
Then you sort your bindings like this Collections.sort(bindings ,SimpleBindingComparator.DEFAULT);
But if your case is more complex than this and your store a Map in the list you should define a logic that represent the order. In your case it can be sad that the order must maintained by c1.getName()
One choice is that you should not create a List but a map of list Map<String>,List<String>> this is so called multi map where a single key matches to multiple values. See MultiMap of guava and if you want it to be sorted then i propose to read about TreeMultiMap
My question might sound silly, but would like to know whether there are any Collection object in Java that does store index,key and values in a single Collection object?
I have the following:
Enumeration hs = request.getParameterNames();
LinkedHashMap<String, String> linkedHashMap = new LinkedHashMap<String, String>();
while (hs.hasMoreElements()) {
linkedHashMap.put(value, request.getParameter(value));
}
The above stores key and value in linkedHashMap, but it doesn't have an index. If it has then I could call by index(pos) and get corresponding key and value.
Edit 1
I would want to conditionally check if index(position) is x then get the corresponding key and value pair and construct a string with query.
As mentioned by others, Java collections does not support this. A workaround is Map<R, Map<C, V>>. But it is too ugly to use.
You can go with Guava. It provides a Table collection type. It has the following format Table<R, C, V>. I haven't tried this but I think this will work for you.
Enumeration hs = request.getParameterNames();
Table<Integer, String, String> table = HashBasedTable.create();
while (hs.hasMoreElements()) {
table.put(index, value, request.getParameter(value));
}
Now, if you want key, value pair at, let's say, index 1. Just do table.row(1). Similarly, to get index, value pairs just do table.column(value).
No Collection in java, will support this.
You need to create a new class IndexedMap inheriting HashMap and store the key object into the
arraylist by overriding put method.
here is the answer(answerd by another user: Adriaan Koster)
how to get the one entry from hashmap without iterating
Maybe you need implementing yourself for achieving this functionality.
public class Param{
private String key;
private String value;
public Param(String key, String value){
this.key = key;
this.value = value;
}
public void setKey(String key){
this.key = key;
}
public String getKey(){
return this.key;
}
public void setValue(String value){
this.value = value;
}
public String getValue(){
return this.value;
}
}
Enumeration hs = request.getParameterNames();
List<Param> list = new ArrayList<Param>();
while (hs.hasMoreElements()) {
String key = hs.nextElement();
list.add(new Param(key, request.getParameter(key)));
}
By doing this, you could get param with an index provided by List API.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Maps with multiple types of values in java
I have an odd question. Maybe I'm going about this the wrong way, but let's see where this question goes :)
I would like a Map container that contains either Strings or lists of Strings. I want to enforce this rule during construction of this object so that you can't create a map with values that aren't either of those.
e.g.
class Record {
public Record(String key, Map<String,Object> attrs) {
// check that attrs only contains Objects which are Strings or List<Strings>
}
}
Other ways I have thought of to solve the problem might be...
1)
class Record {
public Record(String key, Map<String,String> attrs, Map<String,List<String>> multiAttrs) {
// ...
}
}
2)
class Record {
public Record(String key, Map<String,Value> attrs) {
// ...
}
}
class Value {
// Create some funky class that encapsulates lists.
// Perhaps returning the only element in the list if the size is 1,
// but returning the list otherwise
}
I am not immediately excited at the alternatives, but I'm just putting it there as stuff I've already considered. Really I want the distinction between Strings and List to be transparent to the user of the class.
Have you considered ListMultimap? For the single value case the list would only have one element. Multimap allows multiple elements (values) to be mapped to each key. So your method would be:
public Record(String key, ListMultimap<String, String> attrs)...
Also, since your Record seems to be another mapping, consider using Table which allows for two-key mapping.
Check out ArrayListMultimap from Google which will help with this need
You can continue calling put on this map, if you need to get the map in its simplified form you can use this method, or modify it :)
public static Map<Field, String> toSingularMap(ArrayListMultimap<Field, String> map) {
Map<Field, String> singular_map = new HashMap<Field, String>();
if (map != null && !map.isEmpty()) {
Map<Field, Collection<String>> real_map = map.asMap();
for (Iterator<Entry<Field, Collection<String>>> it = real_map
.entrySet().iterator(); it.hasNext();) {
Entry<Field, Collection<String>> entry = it.next();
Field field = entry.getKey();
Collection<String> values = entry.getValue();
String value = null;
if (values != null && !values.isEmpty()) {
ArrayList<String> list = new ArrayList<String>(values);
value = list.get(0);
}
singular_map.put(field, value);
}
}
return singular_map;
}
Or if you do not want to use an extra library, you can create a simple Wrapper class
class Wrap {
String value;
String[] values
}
and have your map use Map<String, Wrap> map, when looping you can then determine either through use of your class methods or just testing, which one of the Wrapper variables are populated
I would use only List<String>. You could maybe add some methods to allow adding a single String and wrap the passed argument using Arrays.asList(...). Using only a single type of objects will reduce the quantity of code to write and avoid many if/else.
Why not create a class
class MyFunkyValue{
private String onlyOneString;
private List<String> stringValues;
public MyFunkyValue(String s){
...
}
public MyFunkyValue(List<String>ls){
...
}
}
and use it like this:
Map<KeyClass,MyFunkyValue> m;