Getting intersection of a keys of a map - java

This is my map
Map<String,Set<Integer>> transactions = new HashMap<String,Set<Integer>>();
This is the Set of string
Set<String> check_set
Now question is how to make this method
Set<Integer> getIntersection(Map<String,Set<Integer>> transactions, Set<String> check_set)
Which will return intersection of all the Set of integers corresponding to the keys in check_set.
If the MAP is
tea=[1,3,5,7,9],
milk=[2,3,6,7,9],
sugar=[1,4,6,8,9]...
and if check_set is {"tea","milk"} then the method should return values which are present in both tea and milk i.e {3,7,9}. Or if it has {"milk","sugar"} then it should return {6,9}. if it has all three {"sugar","milk",tea"} then it should return {3,9}.
I understand I need to use retainAll function to get intersection. But how to formulate a logic to check all sets of integer in map and get their intersection.

EDIT : must use a copy of the first set in map (thanks to Bohemian)
In pseudo-code, you could have
Init result set to null to know it is still not initialized
Loop for each key in check_set
if result is null then result = map{key} // take first set
else result = intersection(result, map{key}) // and keep on intersecting
That gives in java
Set<Integer> result = null;
for (String key: check_set) {
if (result == null) {
result = new HashSet<Integer>(map.get(key));
}
else {
result.retainAll(map.get(key));
}
}

private static Set<Integer> getIntersection(Map<String, Set<Integer>> transactions, Set<String> checkSet) {
Iterator<String> iterator = checkSet.iterator();
// create a copy of the original set
Set<Integer> result = new HashSet<>(transactions.get(iterator.next()));
while (iterator.hasNext()) {
result.retainAll(transactions.get(iterator.next()));
}
return result;
}

Related

Clone an ArrayList to another ArrayList does not work in DP

Here is the Java code to find the shortest concatenation of elements of Array wordBank to construct String Terget, using Dynamic Programming.
Example:
Input: wordBank = {"ab", "c", "d", "abc", "ad"},
Target = "abcd".
Output: {"abc", "d"}.
To do this, I have stored the combination of elements as an ArrayList in a HashMap.
However, the hashMap does not store the values correctly, i.e., the values change when I recursively call the function, although I have cloned the ArrayList before adding it to the map.
Any idea why this happens?
The code works well with arrays.
static ArrayList<String> bestConstruct(String target, String[] wordBank, HashMap<String, ArrayList<String>> map) {
if(target.isEmpty())
{
return new ArrayList<String>();
}
if(map.containsKey(target))
return map.get(target);
ArrayList<String> shortestCombination = null;
for (String word : wordBank) {
if(target.startsWith(word)) {
String newTarget = target.substring(word.length(), target.length());
ArrayList<String> combination = bestConstruct(newTarget, wordBank, map);
if(combination != null) {
combination.add(word);
if(shortestCombination == null || combination.size() < shortestCombination.size())
shortestCombination = (ArrayList<String>)(combination.clone());
}
}
}
map.put(target, (ArrayList<String>) (shortestCombination.clone()));
return shortestCombination;
}
The problem is the interaction between these lines:
if(map.containsKey(target))
return map.get(target);
and
ArrayList<String> combination = bestConstruct(newTarget, wordBank, map);
if(combination != null) {
combination.add(word);
If you return the memoized list, you're updating it before you clone it.
In general, don't rely on callers to "do the right thing": if you don't want the list in the map to be updated, do the copy yourself before you return it:
if(map.containsKey(target))
return new ArrayList<>(map.get(target));
You may also need to handle the case of a string not being able to be constructed from the word bank.

Update HashMap without adding new entry

My program uses two HashmMap and they have exactly the same number of entries and the same keys.
One (tableMap) is static and never changes. The other one is dynamic (partitionMap), this means that I need to update values.
My algorithm got a problem, because seems to be adding one more entry when it is supposed to be not.
//I have a LinkedList of strings that I want to add to the HashMap partitionMap
LinkedList<String> partition = new LinkedList<String>();
for (TerminalNode terminalNode : ctx.U()) {
partition.add(terminalNode.getText());
}
//for each entry of tableMap
for(Entry<String, LinkedList<String>> entry : tableMap.entrySet())
{
//I retrieve keys and values from tableMap
String key = entry.getKey();
LinkedList<String> attributes = entry.getValue();
//the condition: if my linkedlist is included in the other do...
if(attributes.containsAll(partition))
{
//get the list of values
ArrayList<LinkedList<String>> l = partitionMap.get(key);
//but the first time is always null since I init partitionMap without values
if(l==null)
{
ArrayList<LinkedList<String>> firstLL = new ArrayList<LinkedList<String>>();
firstLL.add(partition);
partitionMap.put(key, firstLL); //BUG HERE! add one more entry instead of just updating values
}
else
{
l.add(partition);
partitionMap.put(key, l);
}
}
}
Does anybody have an idea why this is wrong?

Contains if and only if in the Collection class- Java

Map<String, Integer> successors = new HashMap <String, Integer> ();
// I have added some elements into the successors.
Collection<Integer> uniqueValues = successors.values();
Is there a way for me to find out in java if uniqueValues can show me that all the values in it are the same?
I planned on using the if(uniqueValues.contains(1))statement. But I just could not figure it out. Since this statement will say true if 1 is present and other values different from 1 are also present. I just want it to return true if 1 is the only value in the collections.
eg; {1,1,1,1,1,1,1,1,1,1,1,1,1} should return true.
But {1,2,1,3,1,4,2,4,22,1,1,1,4} should return false.
Some code along the lines of "Contains if and only if."
This will be of great help. Thanks in advance.
Do it the CPU-clock-wasting way:
if(new HashSet(successors.values()).size()>1) {...}
Well, you could do something like this (inefficiently),
boolean uniqueValues = new HashSet<Integer>(successors.values()).size() == 1;
Since that will check every value every time, a more efficient approach might be,
boolean uniqueValues = true;
Collection<Integer> values = successors.values();
Iterator<Integer> iter = values.iterator();
if (iter.hasNext()) {
int t = iter.next();
while (iter.hasNext()) {
int i = iter.next();
if (t != i) {
// stop if we find a different value
uniqueValues = false;
break;
}
}
}
Some sort of Set sounds like easiest solution
if(new HashSet<Integer>(successors.values)).size() == 1)
Because Set can contain only unique values, logical consequence of having input collection with same values is the Set of size one. Or you can of course introduce you own util method which will check this condition.

How to update a value for a key in HashMap?

I am having HashMap like this,
HashMap<String,Set<String>> map = new HashMap<String,Set<String>>();
I am trying to do before adding an element in map,
Want to check whether the key exist or not, i can get it by using map.containsKey().
If the key exist, i want check the size of Set respective to that key.
If size <= 1 i want add an element in that set.
I wouldn't use containsKey and get as this means two lookups when you only need one.
private final Map<String,Set<String>> map = new HashMap<String,Set<String>>();
Set<String> set = map.get(key);
if(set != null && set.size() <= 1)
set.add(some$value);
The only problem with this is that the value will always be null unless you set it somewhere so what you may want is
private final Map<String,Set<String>> map = new HashMap<String,Set<String>>();
Set<String> set = map.get(key);
if(value != null)
map.put(key, set = new HashSet<String>());
if (set.size() <= 1)
set.add(some$value);
It is unusual to have a set with a maximum size of 2. Is there any reason for this?
Sounds like this:
HashMap<String,Set<String>> map = new HashMap<String,Set<String>>();
Set<String> value = map.get("key");
if(value != null) {
if(value.size() <= 1) {
value.add("some value");
}
} else {
map.put("key", new HashSet<String>());
}
Now, either the last point was poorly worded (i.e. you want to update the Set associated with the key) or you really want to update the key itself, in which case you'd probably have to just remove it and add a new entry.
You could get the set from the map with map.get(String key).
Then test the size of the Set. If needed, add your element.
Now you can simply remove the old set from the map with map.remove(String key) and reinsert it with put(String, Set);

Iterate Hash Map

I have an hashmap declared as
private HashMap testMessages = null;
I will be storing string values in both key and value part of the hashmap retrieved from oracle table.
I am not concerned about the hashmap keys. I want to retrieve the hashmap values alone and check whether string variable filename is prefixed with one of the hash map value and return true if it's same. I want to ensure that hash map values are not null and empty.
function (string filename)
{..
loop thru hashmap values
check whether the variable file name is prefixed with one of the hashmap values if so
return true
otherwise
return false
}
hashmap example:
key1,prod
key2,test
key3,dummy
filename example:
test123_20012010.csv
should return true since the file name is prefixed with one of the hashmap values
How can i do it?
for (String prefix : map.values()) {
if (filename.startsWith(prefix)) {
return true;
}
}
return false;
It should be noted that this is linear time in the number of entries in the map in the worst case. If you have multiple filename that you want to do the check for, it's much better to preprocess the prefixes and build something like a patricia trie and other fast dictionary-like data structures.
Here's a brute force approach to iterate over the hash map values and check whether filename begins with the value.
// generics version
private HashMap<String, String> testMessages = buildMap();
for (String v : testMessages.values()) {
if (filename.startsWith(v) {
// found a map value that starts the file name
}
}
// alternative non-generics version
private HashMap testMessages; // assigned somewhere
for (Object v : testMessages.values()) {
if (filename.startsWith((String) v) {
// found a map value that starts the file name
}
}
leeched from leepoint.net
public static void iterate_over_hashmap(Map mp) {
Iterator it = mp.entrySet().iterator();
while (it.hasNext()) {
Map.Entry pairs = (Map.Entry)it.next();
System.out.println(pairs.getKey() + " = " + pairs.getValue());
}
}
You have to treat each entry as a key/value pair and iterate over those as a single entity. Then you cast it into Map.Entry and then you can read both separately
function(String fileName)
{
for(String value : hashMap.values())
{
if(fileName.startsWith(value))
return true;
}
return false;
}

Categories