Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
So, I have a HashMap<String, String>
public HashMap<String, String> frozen = new HashMap<String, String>();
and I want to remove a value from it depending on the key. So lets say I put in these
frozen.put("1", "1_1");
frozen.put("1", "1_2");
I want to remove only one of the values, not the whole keyset.
How would I go about doing this? If you still didn't understand, this non-existing method should explain it.
frozen.remove("1", "1_2");
Obviously that doesn't exist, but that's what I want.
Thanks in advance.
It seems the easiest solution would be to use some type of List as your value. In this particular case, it might look something like this:
final Map<String, List<String>> map = new HashMap<String, List<String>>();
final String key = "1";
map.put(key, new LinkedList<String>());
map.get(key).add("1_1");
map.get(key).add("1_2");
And then to remove a value given a particular key (as shown in your question), you may try something like map.get(key).remove("1_2");
You probably have put's parameter order inverted. Duplicate keys are not allowed. New values (for the same key) replace the older. So,
frozen.put("1", "1_1");
frozen.put("1", "1_2");
produces a map with only one entry: key="1", and value="1_2". On the contrary,
frozen.put("1_1", "1" );
frozen.put("1_2", "1" );
produces a map with 2 entries. To remove an entry, you only need to reference its key, as they are unique:
frozen.remove("1_2");
If this doesn't ring a bell, then please be more specific in what the data structure should hold, and what not. A few use cases would help.
What you are doing is not possible. You cannot put in a different value using the same key. You can remove an entry using the remove method, but for something you want, you can checkout something like Guava's MultiMap.
If you really want to remove based on a value, you'll need to iterate through the values of the Map using entrySet(), and then based on the value call the remove method using the found key.
The easiest way to find a solution to such a problem is to consult the JavaDocs: http://docs.oracle.com/javase/7/docs/api/
Find your class there (in your case: java.util.HashMap) and look for the remove method. In this case, you do not need to hand the value to the method (that would be really inefficient). To remove something from a HashMap, simply hand the key to the remove method:
frozen.remove("1");
This will remove the key-value pair "1", "1_2" from the HashMap.
Why will this not remove the first key-value pair? Because the put method overwrites any previous values. To be able to map a key to multiple values, try creating a HashMap with a String and a List:
HashMap<String, ArrayList> frozen = new HashMap<String, ArrayList>();
is a possible example.
I believe you're trying to map multiple strings to one key. It's possible but if you map your key to a List.
public Map<String, List<String>> frozen = new HashMap<String, List<String>>();
Then you can add multiple values to the same key as
public void addToMappedList(Map<String, List<String>> map,
String key, String value) {
List<String> existingValues = map.get(key);
if (existingValues == null) {
existingValues = new ArrayList<String>();
map.put(key, existingValues);
}
existingValues.add(value);
}
addToMappedList(frozen, "1", "1_1");
addToMappedList(frozen, "1", "1_2");
Here's how to go about removing individual values from the List. The boolean returned would indicate if the value was actually found and removed from the List or not.
public boolean removeFromMappedList(Map<String, List<String>> map,
String key, String value) {
List<String> existingValues = map.get(key);
if (existingValues != null) {
return existingValues.remove(value);
}
return false;
}
removeFromMappedList(frozen, "1", "1_1"); // true
removeFromMappedList(frozen, "1", "1_3"); // false
To remove the whole key and the List associated with it just use the Map directly
frozen.remove("1");
Related
I have some inputted String String usrInput; that user could import some string once into App without any case-sensitivity policy like: "start","Start","START","end" ,"END" and etc.
And I have a Map that i inserted my strings for example "start" into that and put it into HashMap<String, String> myMap:
Map<String, String> listOfActions = new HashMap<>();
listOfActions.put(myStr, myStr);
Now I want to check listOfActions members to get for example "start" filed in every case model ("start","Start","START") , currently I do like below:
if (listOfActions.containsKey(usrInput.toUpperCase())
|| listOfActions.containsKey(usrInput.toLowerCase())) {
/// some do
}
So I want to know:
1. Is there any way to get String value without case-sensitivity?
I will also add this here I couldn't use equalsIgnoreCase() method for get items from Map because its return Boolean.
2. I have similar problem in switch-case statements to check 2 string equality without case-sensitivity.
You can use
Map<String, String> listOfActions = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
Other solutions can be Apache's CaseInsensitiveMap or Spring's LinkedCaseInsensitiveMap.
Please see https://www.baeldung.com/java-map-with-case-insensitive-keys for more details about these solutions.
If you only use inputs as map keys (i.e. you don't need to later reproduce the strings in original casing), I suggest just lowercasing all inputs before inserting them into the map:
Map<String, String> listOfActions = new HashMap<>();
listOfActions.put(myStr.toLowerCase(), myStr);
This will simplify locating the values later on, since you know that all keys are already lowercased, so the lookup becomes easy:
if (listOfActions.containsKey(myStr.toLowerCase())) {
// do something
}
When you create a new instance of HashMap, you can override some of its methods, such as put and containsKey like this:
Map<String, String> map = new HashMap<>() {
#Override
public String put(String key, String value) {
return super.put(key.toLowerCase(), value);
}
#Override
public boolean containsKey(Object key) {
return super.containsKey(key.toString().toLowerCase());
}
};
map.put("START", "doStart");
System.out.println(map); // {start=doStart}
System.out.println(map.containsKey("START")); // true
System.out.println(map.containsKey("Start")); // true
System.out.println(map.containsKey("start")); // true
One thing you can do is make everything upper-case or lower-case, then compare them.
string.toLowerCase().equals("other string");
string.toUpperCase().equals("OTHERSTRING");
This way, whether it is lower-case or upper-case, it will only be compared as one or the other, and acts as though it were case insensitive.
I am working on an XML file. In my XML file, there are somes nodes which have childs. This XML file has multiple tags.
<Cat categorie="CAT 1" guid="e9fdsd8ff">
<!--Electric energie management-->
**<item Var="VAR1" guid="2795ddsd410d">
<desc> Energie Smart Management
</desc>
<App guid="240adsqsd" />
<App guid="90dqddqsq" />**
</item>
</Cat>
Like you can see, my node "item " has the argument VAR=var1 and has 2 childs.
So I created a hashMap to put, for 1 node his childs like below
private Map<String, Collection <String >> multiMap = new HashMap <> ();
So I Have something like that actually : [Key=Var1, Value = [gui0,guid1,...]]
Now, I would like to know if you knew how to verify if a guid is contained in a collection associated with a key in order to retrieve this key.
For example, if I have this String : 240adsqsd. I want to recover Var1.
Thanks for your help
It is possible.
Say you have the key myKey and you want to know if the string mySearchString is contained in the collection behind that key.
multiMap.get("myKey").contains("mySearchString");
It will return true if mySearchString equals (case sensitive) any object in the colelction.
You have to be careful though, the method contains on a collection uses the case sensitive equals method and will only work when they are 100% equal. So when your collection contains something like "MYSEARCHstring", it won't work, as well as "The sentence that contains mySearchString".
EDIT:
(Thanks Nikolas and Dici)
Here a more complete example how to achieve that.
String mySearchString = "mySearchString";
Map<String, Collection<String>> multiMap = new HashMap<>();
for (String key : multiMap.keySet()) {
if (multiMap.get(key) != null && multiMap.get(key).contains(mySearchString)) {
return key;
}
}
If you don't know the key, you have to iterate over your map, check if one of the collections contains the searched string and then, when you found the collection (and its key) return the key.
A test without map modification would be:
boolean contained = multiMap.getOrDefault(key, Collections.emptyList()).contains(key);
Then there are Map.computeIfAbsent, computeIfPresent, merge if you want to update the map.
If I understand your question, you actually want to reverse your map because a map is good at accessing a value given a key not at finding a key given a value. Here's some pseudo-code to build the map:
map = new Map()
for item in items
for app in item.apps
map.put(app.guid, item.guid) // assuming guids are always unique
That would give you a Map<String, String> rather than Map<String, Collection<String>>. The former is good at telling you which item contains an application, the later is good at telling you which apps a given item contains. Given your reverse mapping map, you will be able to do the following:
// could just have Map<App, Item> appToItem if you build your map differently
// and App and Item define hashCode and equals
public boolean findVar(String appId, Map<String, String> appToItem, Map<String, Item> itemsById) {
Item item = itemsById.get(appToItem.get(appId));
if (item == null) return null;
return item.getVar();
}
Thank you to everyone for your answers.
If I understand correctly, it is preferable that I look for a value not his key.
So let's admit that I choose this option.
Can I recure each value for a key.
If my key is Var1 for example, would it be better for me to recover all its values?
I'm checking to see if a key in my HashMap exists, if it does, I also want to check to see if any other keys have a value with the same name as that of the original key I checked for or not.
For example I have this.
System.out.println("What course do you want to search?");
String searchcourse = input.nextLine();
boolean coursefound = false;
if(hashmap.containsKey(searchcourse) == true){
coursefound = true;
}
This checks to see if the key exists in my hashmap, but now I need to check every single key's values for a specific value, in this case the string searchcourse.
Usually I would use a basic for loop to iterate through something like this, but it doesn't work with HashMaps. My values are also stored in a String ArrayList, if that helps.
You will want to look at each entry in the HashMap. This loop should check the contents of the ArrayList for your searchcourse and print out the key that contained the value.
for (Map.Entry<String,ArrayList> entries : hashmap.entrySet()) {
if (entries.getValue().contains(searchcourse)) {
System.out.println(entries.getKey() + " contains " + searchcourse);
}
}
Here are the relevant javadocs:
Map.Entry
HashMap entrySet method
ArrayList contains method
You can have a bi-directional map. E.g. you can have a Map<Value, Set<Key>> or MultiMap for the values to keys or you can use a bi-directional map which is planned to be added to Guava.
As I understand your question, the values in your Map are List<String>. That is, your Map is declares as Map<String, List<String>>. If so:
for (List<String> listOfStrings : myMap.values()) [
if (listOfStrings .contains(searchcourse) {
// do something
}
}
If the values are just Strings, i.e. the Map is a Map<String, String>, then #Matt has the simple answer.
I currently have a map which stores the following information:
Map<String,String> animals= new HashMap<String,String>();
animals.put("cat","50");
animals.put("bat","38");
animals.put("dog","19");
animals.put("cat","31");
animals.put("cat","34");
animals.put("bat","1");
animals.put("dog","34");
animals.put("cat","55");
I want to create a new map with total for unique items in the above map. So in the above sample, count for cat would be 170, count for bat would be 39 and so on.
I have tried using Set to find unique animal entries in the map, however, I am unable to get the total count for each unique entry
First, don't use String for arithmetic, use int or double (or BigInteger/BigDecimal, but that's probably overkill here). I'd suggest making your map a Map<String, Integer>.
Second, Map.put() will overwrite the previous value if the given key is already present in the map, so as #Guy points out your map actually only contains {cat:55, dog:34, bat:1}. You need to get the previous value somehow in order to preserve it.
The classic way (pre-Java-8) is like so:
public static void putOrUpdate(Map<String, Integer> map, String key, int value) {
Integer previous = map.get(key);
if (previous != null) {
map.put(key, previous + value);
} else {
map.put(key, value);
}
}
Java 8 adds a number of useful methods to Map to make this pattern easier, like Map.merge() which does the put-or-update for you:
map.merge(key, value, (p, v) -> p + v);
You may also find that a multiset is a better data structure to use as it handles incrementing/decrementing for you; Guava provides a nice implementation.
As Guy said. Now you have one bat, one dog and one cat. Another 'put's will override your past values. For definition. Map stores key-value pairs where each key in map is unique. If you have to do it by map you can sum it just in time. For example, if you want to add another value for cat and you want to update it you can do it in this way:
animals.put("cat", animals.get("cat") + yourNewValue);
Your value for cat will be updated. This is for example where our numbers are float/int/long, not string as you have. If you have to do it by strings you can use in this case:
animals.put("cat", Integer.toString(Integer.parseInt(animals.get("cat")) + yourNewValue));
However, it's ugly. I'd recommend create
Map<String, Integer> animals = new HashMap<String, Integer>();
Is there a way to add a key to a HashMap without also adding a value? I know it seems strange, but I have a HashMap<String, ArrayList<Object>> amd I want to first be able to create keys as needed and then check if a certain key exists and, if so, put the appropriate value, namely the ArrayList<Object>
Was that confusing enough?
Since you're using a Map<String, List<Object>>, you're really looking for a multimap. I highly recommend using a third-party library such as Google Guava for this - see Guava's Multimaps.
Multimap<String, Object> myMultimap = ArrayListMultimap.create();
// fill it
myMultimap.put("hello", "hola");
myMultimap.put("hello", "buongiorno");
myMultimap.put("hello", "สวัสดี");
// retrieve
List<String> greetings = myMultimap.get("hello");
// ["hola", "buongiorno", "สวัสดี"]
Java 8 update: I'm no longer convinced that every Map<K, SomeCollection<V>> should be rewritten as a multimap. These days it's quite easy to get what you need without Guava, thanks to Map#computeIfAbsent().
Map<String, List<Object>> myMap = new HashMap<>();
// fill it
myMap.computeIfAbsent("hello", ignored -> new ArrayList<>())
.addAll(Arrays.asList("hola", "buongiorno", "สวัสดี");
// retrieve
List<String> greetings = myMap.get("hello");
// ["hola", "buongiorno", "สวัสดี"]
I'm not sure you want to do this. You can store null as a value for a key, but if you do how will be able to tell, when you do a .get("key") whether the key exists or if it does exist but with a null value? Anyway, see the docs.
You can put null values. It is allowed by HashMap
You can also use a Set initially, and check it for the key, and then fill the map.
Yes, it was confusing enough ;) I don't get why you want to store keys without values instead just putting empty arraylists instead of null.
Adding null may be a problem, because if you call
map.get("somekey");
and receive a null, then you do not know, if the key is not found or if it is present but maps to null...
//This program should answer your questions
import java.util.*;
public class attemptAddingtoHashMap { //Start of program
//MAIN METHOD #################################################
public static void main(String args[]) { //main begins
Map<String, ArrayList<Object>> hmTrial = new HashMap<String, ArrayList<Object>>();
ArrayList alTrial = new ArrayList();//No values now
if (hmTrial.containsKey("first")) {
hmTrial.put("first", alTrial); }
else {hmTrial.put("first",alTrial);}
//in either case, alTrial, an ArrayList was mapped to the string "first"
//if you choose to, you can also add objects to alTrial later
System.out.println("hmTrial is " + hmTrial); //empty now
alTrial.add("h");
alTrial.add("e");
alTrial.add("l");
alTrial.add("l");
alTrial.add("o");
System.out.println("hmTrial is " + hmTrial);//populated now
} //end of main
//#############################################################################################################
} //end of class
//Note - removing objects from alTrial will remove the from the hashmap
//You can copy, paste and run this code on https://ide.geeksforgeeks.org/