I want to write a program that prints out entries "0" and "4" of the HashMap (i.e. entry.getKey(0) and entry.getKey(4) but it won't let me do this) What would be another way using what I already have?
Basically I have this:
HashMap<String, Integer> hm = new HashMap<String, Integer>();
I can iterate over each entry using this code:
for (Map.Entry<String,Integer> entry : hm.entrySet())
{
System.out.println(entry.getKey() + "/" + entry.getValue());
}
Since people have asked for more contextual information, I am storing a set of strings in the HashMap. For example the 0th entry is "Bob", the 1st entry is "Mindy", the 2nd is "Yasser", the 3rd is "Greg" and the 4th is "Jacky." I want the program to print out the 0th and 4th entries of the populated HashMap.
If you are specific about the keys in the Map, you can directly use get() method.Like this,
Integer value = hm.get("0");
If you want to iterate then use something like the code below :
HashMap<String, Integer> hm = new HashMap<String, Integer>();
for (Entry<String, Integer> entry : hm.entrySet())
{
String key = entry.getKey();
if(key.equals("0") || key.equals("1"))
System.out.println(key + "/" + entry.getValue());
}
You cannot pass index to the getKey() method like getKey(0) etc. Refer the documentation.
HashMap class makes no guarantees as to the order of the map; in particular, it does not guarantee that the order will remain constant over time. So, if you are looking to fetch values from a HashMap based on index, probably it is not possible. Closest to your requirement will be something like LinkedHashMap, which maintains the order of keys for insertion/access order.
HashMap works on principle of hashing, we have put(key, value) and get(key) method for storing and retrieving Objects from HashMap. When we pass Key and Value object to put() method on Java HashMap, HashMap implementation calls hashCode() method on Key object and applies returned hashcode() into its own hashing function to find a bucket location for storing Entry object, important point to mention is that HashMap in Java stores both key and value object as Map.Entry in bucket which is essential to understand the retrieving logic.
The HashMap has no defined ordering of keys. You may use LinkedHashMap instead of HashMap It will always return keys in same order (as insertion) when calling keySet(). And then you pick the 0th or 4th key.Later you can retrieve the value for the keys you fetched at 0th and 4th location.
I would recommend simply using the get() method with the provided key. Iteration is not necessary in this case.
Since people have asked for more contextual information, I am storing a set of strings in the HashMap. For example the 0th entry is "Bob", the 1st entry is "Mindy", the 2nd is "Yasser", the 3rd is "Greg" and the 4th is "Jacky." I want the program to print out the 0th and 4th entries of the populated HashMap.
With how it is being used, an HashMap makes no sense. Use a String[] instead!
String[] names = {"Bob", "Mindy", "Yasser", "Greg", "Jacky" };
System.out.println("When " + names[0] + " met " + names[4]);
Why not a targeted approach:
String[] targets = {"0", "4"};
for (String target : targets) {
System.out.println(target + "/" + hm.get(target));
}
Way more efficient than the "big hammer" full iteration approach, and you get output order for free.
If you have a lot of entries in your Map you may considerate to use one of the navigable collections, like TreeMap.
NavigableMap<String,String> map = new TreeMap<>()
map.subMap("0", true, "4", true);
Visit: http://docs.oracle.com/javase/6/docs/api/java/util/NavigableMap.html
Related
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>();
So I've finished a program and have had help building it/worked with another person. I understand all of the program in terms of what each line of code does except one part. This is the code:
Set<String> set1 = firstWordGroup.getWordCountsMap().keySet();
Map<String, Integer> stringIntegerMap1 = set1.stream().collect(HashMap::new,
(hashMap, s) -> hashMap.put(s, s.length()), HashMap::putAll);
stringIntegerMap1.forEach((key,value) ->System.out.println(key + " : "+value));
Some background info:
getWordCut is a method that looks like this:
public HashMap getWordCountsMap() {
HashMap<String, Integer> myHashMap = new HashMap<String, Integer>();
for (String word : this.getWordArray()) {
if (myHashMap.keySet().contains(word)) {
myHashMap.put(word, myHashMap.get(word) + 1);
} else {
myHashMap.put(word, 1);
}
}
return myHashMap;
}
firstWordGroup is a constructor that stores a string of words.
If anybody could explain exactly what this block of code does and how it does it then that would be helpful, thanks.
P.S: I'm not sure if supplying the whole program to reproduce the code is relevant so if you think it is, just leave a comment saying so and I will edit the question so you can reproduce the program.
getWordsCountsMap() returns a map where the key is a word and the value is how many times the word occurred in the array
Set<String> set1 = firstWordGroup.getWordCountsMap().keySet();
The .keyset() method returns just the keys of the map, so now you have a set of the words, but have lost the occurrence counts.
Map<String, Integer> stringIntegerMap1 =
set1.stream()
.collect(HashMap::new,
(hashMap, s) -> hashMap.put(s, s.length()),
HashMap::putAll)
This is using Java8 streams to iterate through the set (words) originally put into a map and create a new hash map, where the key is the word (as it was before) and the value is the length of the word (whereas originally it was the word count). A new hash map is created and populated and returned.
What I'm not understanding is the final HashMap::putAll() which would seem to take the hashmap just populated and re-add all entries (which really would be a no-op because the keys would be replaced). Since I haven't whipped open my IDE to put in the code and test it (which, if you haven't yourself, would recommend, I'm just not interested enough to do so because it's not my problem!).
stringIntegerMap1.forEach((key,value) ->System.out.println(key + " : "+value));
In essence, this is a cleaner way to iterate through the entries in the map created, printing out the word and length for each.
After working through this and thinking about it, I have a feeling I'm doing your homework for you, the real way to figure this out is to break things down and debug through your IDE and seeing what each step of the way does.
Set<String> set1 = firstWordGroup.getWordCountsMap().keySet();
This line calles getWordCountsMap which returns a map from words to their count. It then ignores the count and just takes the words in a set. Note this could be achieved in a lot of much simpler ways.
Map<String, Integer> stringIntegerMap1 = set1.stream()
.collect(HashMap::new, (hashMap, s) -> hashMap.put(s, s.length()), HashMap::putAll);
This converts the set of words to a stream and then collects the stream. The collector starts by creating a hash map then, for each word, adding a map from the to its length. If multiple maps are created (as is allowed in streams) then they are combined using putAll. Again there are much simpler and clearer ways to achieve this.
stringIntegerMap1.forEach((key,value) ->System.out.println(key + " : "+value));
This line iterates through all entries in the map and prints out the key and value.
All this code could have been achieved with:
Arrays.stream(getWordArray())
.distinct().map(w -> w + ":" + w.length()).forEach(System.out::println);
This command converts the words to a stream, removes duplicates, maps the words to the output string then prints them.
I have this hashmap of students which stores the id, name and last name.
So I created this :
Map<Interger, HashMap<String,String>> students = new HashMap<>();
where the second hashmap stores the name and lastname.
My goal is to look for a student in a swing application, I succeed in searching with id because it's the key of the first hashmap, but i'd like to use all of them like this:
So my question is : If I want to search by name or last name, how can i get the value of the first hashmap and put it in a new hashmap ?
You can iterate on the hashmap like this :
private int searchByName(String s) {
for(Map.Entry<Integer, HashMap<String, String>> entry : students.entrySet()) {
HashMap student = entry.getValue(); // Hashmap containing first and lastname
if (student.containsKey(s)) // If name match
return entry.getKey(); // Return the student ID
}
return 0; // Student not found
}
For the lastname just use containsValue(s) instead of containsKey(s)
You can use the Google Collections API Guava for that specifically a BiMap
A bimap (or "bidirectional map") is a map that preserves the
uniqueness of its values as well as that of its keys. This constraint
enables bimaps to support an "inverse view", which is another bimap
containing the same entries as this bimap but with reversed keys and
values.
With this you'will be able to search using first name and last name. This BiMap will be value to your first parent hashmap.
I am not sure if the data structure is the best for your use-case but answering to your question, you should try using values() method which would return you the collection of values of the Map
http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#values()
Collection res = studensts.values();
Iterator<HashMap<String, String>> i = res.iterator();
Map<String,String> resM = null;
while(i.hasNext()){
resM = i.next();
}
I have a Hashmap which may contain wildcards (*) in the String.
For instance,
HashMap<String, Student> students_;
can have John* as one key. I want to know if JohnSmith matches any elements in students_. There could be several matches for my string (John*, Jo*Smith, etc). Is there any way I can get a list of these matches from my HashMap?
Is there another object I could be using that does not require me to iterate through every element in my collection, or do I have to suck it up and use a List object?
FYI, my collection will have less than 200 elements in it, and ultimately I will want to find the pair that matches with the least amount of wildcards.
It's not possible to achieve with a hasmap, because of the hashing function. It would have to assign the hash of "John*" and the hash of "John Smith" et al. the same value.
You could make it with a TreeMap, if you write your own custom class WildcardString wrapping String, and implement compareTo in such a way that "John*".compareTo("John Smith") returns 0. You could do this with regular expressions like other answers have already pointed out.
Seeing that you want the list of widlcard matchings you could always remove entries as you find them, and iterate TreeMap.get()'s. Remember to put the keys back once finished with a name.
This is just a possible way to achieve it. With less than 200 elements you'll be fine iterating.
UPDATE: To impose order correctly on the TreeSet, you could differentiate the case of comparing two WildcardStrings (meaning it's a comparation between keys) and comparing a WildcardString to a String (comparing a key with a search value).
You can use regex to match, but you must first turn "John*" into the regex equivalent "John.*", although you can do that on-the-fly.
Here's some code that will work:
String name = "John Smith"; // For example
Map<String, Student> students_ = new HashMap<String, Sandbox.Student>();
for (Map.Entry<String, Student> entry : students_.entrySet()) {
// If the entry key is "John*", this code will match if name = "John Smith"
if (name.matches("^.*" + entry.getKey().replace("*", ".*") + ".*$")) {
// do something with the matching map entry
System.out.println("Student " + entry.getValue() + " matched " + entry.getKey());
}
}
You can just iterate your Map without converting it into a list, and use the String matches function, wih uses a regexp.
If you want to avoid the loop, you can use guava like this
#Test
public void hashsetContainsWithWildcards() throws Exception {
Set<String> students = new HashSet<String>();
students.add("John*");
students.add("Jo*Smith");
students.add("Bill");
Set<String> filteredStudents = Sets.filter(students, new Predicate<String>() {
public boolean apply(String string) {
return "JohnSmith".matches(string.replace("*", ".*"));
}
});
assertEquals(2, filteredStudents.size());
assertTrue(filteredStudents.contains("John*"));
assertTrue(filteredStudents.contains("Jo*Smith"));
}