First of all, this is my code (just started learning java):
Queue<String> qe = new LinkedList<String>();
qe.add("b");
qe.add("a");
qe.add("c");
qe.add("d");
qe.add("e");
My question:
Is it possible to add element to the queue with two values, like:
qe.add("a","1"); // where 1 is integer
So, that I know element "a" have value 1. If I want to add a number let say "2" to element a, I will have like a => 3.
If this cant be done, what else in java classes that can handle this? I tried to use multi-dimention array, but its kinda hard to do the queue, like pop, push etc. (Maybe I am wrong)
How to call specific element in the queue? Like, call element a, to check its value.
[Note]
Please don't give me links that ask me to read java docs. I was reading, and I still dont get it. The reason why I ask here is because, I know I can find the answer faster and easier.
You'd want to combine a Queue<K> with a Map<K,V>:
Put the keys (e.g. "a", "b") into the Queue<K>
Assign the mapping of the keys to values (e.g. "a"=>3) in the Map<K,V>
I think you're asking for a dictionary type in Java.
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("a", 1);
map.put("b", 2);
You can then access them by key - in this case the String you choose as the key.
int value = map.get("a");
Value in this case will return 1.
Is that what you want?
You want to use a HashMap instead of LinkedList. HashMap is a dictionary-like structure that allows you to create associations, for instance a=>1.
Check out JavaDocs for HashMap to get a grasp how to use it:-).
I think what you are asking for is LinkedHashMap which is a combination of a Queue and a HashMap. While you are able to store the key and value pairs, it would also remember the order like Queue does. The only thing is you'd have to use an iterator since there is no poll() method, however you can visit each element in the order that they were added.
Related
I basically need to know if my HashMap has different keys that map to the same value. I was wondering if there is a way other than checking each keys value against all other values in the map.
Update:
Just some more information that will hopefully clarify what I'm trying to accomplish. Consider a String "azza". Say that I'm iterating over this String and storing each character as a key, and it's corresponding value is some other String. Let's say I eventually get to the last occurrence of 'a' and the value is already be in the map.This would be fine if the key corresponding with the value that is already in the map is also 'a'. My issue occurs when 'a' and 'z' both map to the same value. Only if different keys map to the same value.
Sure, the fastest to both code and execute is:
boolean hasDupeValues = new HashSet<>(map.values()).size() != map.size();
which executes in O(n) time.
Sets don't allow duplicates, so the set will be smaller than the values list if there are dupes.
Very similar to EJP's and Bohemian's answer above but with streams:
boolean hasDupeValues = map.values().stream().distinct().count() != map.size();
You could create a HashMap that maps values to lists of keys. This would take more space and require (slightly) more complex code, but with the benefit of greatly higher efficiency (amortized O(1) vs. O(n) for the method of just looping all values).
For example, say you currently have HashMap<Key, Value> map1, and you want to know which keys have the same value. You create another map, HashMap<Value, List<Key>> map2.
Then you just modify map1 and map2 together.
map1.put(key, value);
if(!map2.containsKey(value)) {
map2.put(value, new ArrayList<Key>);
}
map2.get(value).add(key);
Then to get all keys that map to value, you just do map2.get(value).
If you need to put/remove in many different places, to make sure that you don't forget to use map2 you could create your own data structure (i.e. a separate class) that contains 2 maps and implement put/remove/get/etc. for that.
Edit: I may have misunderstood the question. If you don't need an actual list of keys, just a simple "yes/no" answer to "does the map already contain this value?", and you want something better than O(n), you could keep a separate HashMap<Value, Integer> that simply counts up how many times the value occurs in the map. This would take considerably less space than a map of lists.
You can check whether a map contains a value already by calling map.values().contains(value). This is not as efficient as looking up a key in the map, but still, it's O(n), and you don't need to create a new set just in order to count its elements.
However, what you seem to need is a BiMap. There is no such thing in the Java standard library, but you can build one relatively easily by using two HashMaps: one which maps keys to values and one which maps values to keys. Every time you map a key to a value, you can then check in amortized O(1) whether the value already is mapped to, and if it isn't, map the key to the value in the one map and the value to the key in the other.
If it is an option to create a new dependency for your project, some third-party libraries contain ready-made bimaps, such as Guava (BiMap) and Apache Commons (BidiMap).
You could iterate over the keys and save the current value in the Set.
But, before inserting that value in a Set, check if the Set already contains that value.
If this is true, it means that a previous key already contains the same value.
Map<Integer, String> map = new HashMap<>();
Set<String> values = new HashSet<>();
Set<Integter> keysWithSameValue = new HashSet<>();
for(Integer key : map.keySet()) {
if(values.contains(map.get(key))) {
keysWithSameValue.add(key);
}
values.add(map.get(key));
}
Can someone suggest me a datatype/structure in java that satisfies:
1) no fixed size
2) does not automatically sort data. Data should be stored in the order in which it arrives
3) it should store only unique entries
4) its elements are accessible or atleast the first element should be!
links are not able to maintain unique entries.
I tried working with Sets but it changes the order of my data automatically which i dont want to let happen.
So i am now trying to work my way with LinkedHashSet, but I am not able to find the exact way to access the first element of the same for comparision.
Any suggestions please. Thanks!
You can use LinkedHashSet if you don't wanna write your own structure. Getting elements may be kinda tricky, try this:
Integer lastInteger = set.stream().skip(set.size()-1).findFirst().get();
This is gonna get the last element, if you want different elements you need to skip a different count. This is only one of the ways, you can get an iterator and iterate yourself etc. Remember to override hashCode and equals when working with sets.
LinkedHashSet is the right data structure for your requirements.
You can access the first element like so:
Set<String> set = new LinkedHashSet<>();
set.add("a");
set.add("b"); // And so on
// Retrieve first element
// Will throw NoSuchElementException if set is empty
String firstElement = set.iterator().next();
// Retrieve and remove first element
Iterator<String> i = set.iterator();
String otherFirstElement = i.next();
i.remove();
For accessing other elements, see answer from #Whatzs.
If I properly understand your question, you are looking for a data structure that would combine the properties of a Set and an ArrayList, a kind of "ArraySet".
I haven't found anything in the core java for that but it looks like the Android JDK has such a data structure.
https://developer.android.com/reference/android/util/ArraySet.html
https://android.googlesource.com/platform/frameworks/base/+/master/core/java/android/util/ArraySet.java
One solution might be to build your own based on the android implementation.
I want to store some words and their occurrence times in a website, and I don't know which structure I should use.
Every time I add a word in the structure, it first checks if the word already exists, if yes, the occurrence times plus one, if not, add the word into the structure. Thus I can find an element very fast by using this structure. I guess I should use a hashtable or hashmap, right?
And I also want to get a sorted list, thus the structure can be ranked in a short time.
Forgot to mention, I am using Java to write it.
Thanks guys! :)
A HashMap seems like it would suit you well. If you need a thread-safe option, then go with ConcurrentHashMap.
For example:
Map<String, Integer> wordOccurenceMap = new HashMap<>();
"TreeMap provides guaranteed O(log n) lookup time (and insertion etc), whereas HashMap provides O(1) lookup time if the hash code disperses keys appropriately. Unless you need the entries to be sorted, I'd stick with HashMap." -part of Jon Skeet's answer in TreeMap or HashMap.
TreeMap is the better solution, if you want both Sorting functionality and counting words.
Custom Trie can make more efficient but it's not required unless you are modifying the words.
Define a Hashmap with word as the key and counter as the value
Map<String,Integer> wordsCountMap = new HashMap<String,Integer>();
Then add the logic like this:
When you get a word, check for it in the map using containsKey method
If key(word) is found, fetch the value using get and increment the value
If key(word) is not found, add the value using thw word as key and put with count 1 as value
So, you could use HashMap, but don't forget about multythreading. Is this data structure could be accessed throught few thread? Also, you could use three map in a case that data have some hirarchy (e.g. in a case of rakning and sort it by time). Also, you could look throught google guava collections, probably, they will be more sutabile for you.
Any Map Implementation Will Do. If Localized Changes prefer HashMap otherWise
ConcurrentHashMap for multithreading.
Remember to use any stemming Library.
stemming library in java
for example working and work logically are same word.
Remember Integer is immutable see example below
Example :
Map<String, Integer> occurrence = new ConcurrentHashMap<String, Integer>();
synchronized void addWord(String word) { // may need to synchronize this method
String stemmedWord = stem(word);
Integer count = occurrence.get(stemmedWord)
if(count == null) {
count = new Integer(0);
}
count ++;
occurrence.put(stemmedWord, count);
**// the above is necessary as Integer is immutable**
}
I have a hashmap that contains 10 children hashmap, each of these child hashmap 5 keys mapping to a String array. When I want to update a value for a specific key from a children hashmap, all the keys get updated instead; not only that, but also all the children hashmap get updated as well. This code illustrate what I'm doing.
HashMap<String, HashMap<String, String[]>> parentMap = new HashMap<String, HashMap<String, String[]>>();
for(String x : someArray){ // Adds 10 children hashmaps to parentMap
parentMap.put(x,new HashMap<String, String[]>());
for(String y : someOtherArray){ // Creates 5 keys for each of the children hashmaps
parentMap.get(x).put(y,stringArray);
}
}
parentMap.get(someKey).put(someOtherKey,modifiedArray); // This updates the entry I want to update.
When I update with that last instruction, I want to update specifically that key, however everything gets updated instead, all the keys for all the children hashmaps are updated instead the one I want.
Hopefully it makes sense, I'm not sure if this is the correct approach for this but I've been looking online for any tips on doing something similar without any luck. I'm not good at all with Java, if I can achieve the same result with something simpler, it will be welcome, note that I can't use a List or something like that, since it uses int indexes, I need to reference to my objects using a string (like a dictionary on python).
That is because you initialize all maps to contain stringArray, i.e., the same array.
This is why changing one of them, will change all of them.
If you want each key in each inner map to point to different copies of the array, you need to do something like
...
parentMap.get(x).put(y, Arrays.copyOf(stringArray, stringArray.length));
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^
...
(You could also use for instance clone or create new arrays manually each time you need a new copy.)
#aioobe explained the reason.
Here is the solution. You have to create copy of initial array every time you put it into your map:
String[] tmpArr = new String[stringArray.length];
arraycopy(stringArr, 0, tmpArr, 0, stringArray.length);
parentMap.get(x).put(y,stringArray);
If i use:
HashMap<String, Integer> test = new HashMap<String, Integer>();
Or i use:
HashMap test = new HashMap();
Is there any difference on further methods that i can apply on test object. like test.put(), test.get() etc if initialized differently??
Also if i put something in test object e.g like:
test.put("One", new Integer(5));
test.put("Two", new Integer(4));
test.put("Three", new Integer(3));
and display it as:
Set set = tokens.entrySet();
Iterator ik = test.iterator();
while(ik.hasNext()){
Map.Entry me = (Map.Entry)ik.next();
System.out.println(me.getKey() + " : " + me.getValue() );
The result is not sorted, restul is:
Three: 3
One: 5
Two: 1
What rule it does follow?? Is this normal behavior for the output to be randomly displayed??
In the first case Hashmap keys must be Strings and values must be Integers. The compiler will perform the respective type checking. In the second case any kind of objects can be used.
This is completely normal that your HashMap entries are printed in random order. If you want to preserve the order use LinkedHashMap instead.
In first example you can only put Strings as keys and Integers as values, but in second example you can put anything to the map and the compiler can't help you to get type safety.
Read more about how Java Generics works.
Yes, you'll get "random" iteration order when using HashMap. If you need a Map implementation with predictable iteration order, check out LinkedHashMap.
In the first case, key must be String and value must be Integer.
In the second case, key and value can be object of anytype.
HashMap and HashSet does not guarantee the insertion order. If you want it to remain in the order at which you insert the value, try LinkedHashMap. Much clearer was answered in previous StackOverflow question here
I think that depends on your usage ,
if you need a compiler to allow you to add only String as Key and Integer as value , then you need to specify both parameters type,
otherwise if you need to pass anything without any restriction then use the second one.