java- How to find intersection of values in Hashset in loop? - java

I wrote a program in Java where it retrieves records from a database table and stored them in a hashmap.
The keys and values of them are like the following:
Key(represent words) Values(represent filename)
w1 file1
w2 file1
w3 file2
w4 file1
w5 file2
w6 file1,file2
............
The list goes on and on but this is just an idea of how it looks like.As you can see, there's no duplicate for words and they are unique.
Given that I have this hashmap info,I need to find the intersection of the key and it's next key and return the results of the intersection. The idea looks like this:
w1∩w2= file1
w2∩w3= empty
w3∩w4= empty
........and it keeps going until it reaches the finishes the final pair of keys in the hashmap.
Since the pair of intersection results depends on the number of keys in the hashmap,I am guessing I'll need to use some loop to keep it iterating to return all the results.
Is there a way on how to get the intersection of each subsequent keys and also a way that is optimize regardless the size of the hashmap?
I appreciate any suggestion.

Make a variable that will hold all those intersections. In your loop retrieve 2 keys at a time. Compare each values of the 2 keys and if they are the same add the value to your intersection holder. Repeat the steps until there is no more pairs.
Here is the code.
Add this below your try/catch
LinkedHashmap<String, Set<String>> intersectionMap = new LinkedHashmap<>();
if (map.keySet() != null) {
String[] keys = map.keySet().toArray(new String[map.keySet().size()]);
for (int i = 0; i < keys.length - 1; i++) {
String key1 = keys[i];
String key2 = keys[i + 1];
TreeSet<String> interSection = intersection(map.get(key1), map.get(key2));
intersectionMap.put(key1 + "∩" + key2, interSection);
}
}
Add this helper method. This method will find the intersection of the two sets. This will be the key in solving your problem.
public static TreeSet<String> intersection(TreeSet<String> setA, TreeSet<String> setB) {
// An optimization to iterate over the smaller set
if (setA.size() > setB.size()) {
return intersection(setB, setA);
}
TreeSet<String> results = new TreeSet<>();
for (String element : setA) {
if (setB.contains(element)) {
results.add(element);
}
}
return results;
}

Yet another version with set operations:
Map<String>, Set<String>> intersections(Map<String, TreeSet<String>> map) {
Map<String>, Set<String>> result = new TreeMap<>();
List<String> words = new ArrayList<>(map.keySet());
words.sort();
for (int i = 0; i < words.size() - 1; ++i) {
String wordI = words.get(i);
Set<String> valueI = map.get(wordI);
for (int j = i + 1, j < words.size(); ++j) {
String wordJ = words.get(j);
Set<String> valueJ = map.get(wordJ);
String word = wordi + "∩" + words[j];
Set<String> value = new TreeSet<>(valueI);
value.retainAll(valueJ);
result.put(word, value);
}
}
return result;
}

Related

Creating a HashMap of chars in a string and integers in an ArrayList<integer>

I have to create a HashMap that records the letters in a string and their index values in a ArrayList, so that if the HashMap is called with some string key, each related index integer is returned, and so that the map can be called by itself such that each key is shown with their indexes, For example for the string "Hello World", the map would look something like:
d=[9], o=[4, 6], r=[7], W=[5], H=[0], l=[2, 3, 8], e=[1].
I'm really confused by the requirement of the inputs as String and ArrayList, rather than chars and integers. Could you explain to me the relationship of the map to those objects, and to their components which are ultimately what are recorded as keys and values? When trying to debug, it stops processing before the map call.
The error message is:
java.lang.AssertionError: Wrong number of entries in Concordance. Expected: 5. Got: 1
Expected :1
Actual :5
But I really think I'm not grasping HashMap very well, so I'd appreciate if anyone could guide me through the basics, or provide anything educational about using HashMap, especially ones that use ArrayList.
public HashMap<String, ArrayList<Integer>> concordanceForString(String s) {
HashMap<String, ArrayList<Integer>> sMap = new HashMap<>();//create map "sMap"
char[] sArray = new char[s.length()]; //create character array, "sArray", for string conversion
ArrayList<Integer> sCharIndex = new ArrayList<Integer>();
for (int i = 0; i < s.length(); i++) {
sArray[i] = s.charAt(i); // convert string into array
}
for (int j = 0; j < sArray.length; j++){
sCharIndex.add(j); // add char indexes to index ArrayList
}
sMap.put(s, sCharIndex); //add the String and ArrayList
return sMap; // I feel like this should be sMap.get(s) but when I do, it gives me the zigzag red underline.
}
Here is a way to do it:
String input = "hello world";
Map<String, List<Integer>> letters = new HashMap<String, List<Integer>>();
// remove all whitespace characters - since it appears you are doing that
String string = input.replaceAll("\\s", "");
// loop over the length of the string
for (int i = 0; i < string.length(); i++) {
// add the entry to the map
// if it does not exist, then a new List with value of i is added
// if the key does exist, then the new List of i is added to the
// existing List
letters.merge(string.substring(i, i + 1),
Arrays.asList(i),
(o, n) -> Stream.concat(o.stream(), n.stream()).collect(Collectors.toList()));
}
System.out.println(letters);
that gives this output:
{r=[7], d=[9], e=[1], w=[5], h=[0], l=[2, 3, 8], o=[4, 6]}
EDIT - this uses a Character as the key to the map:
String input = "hello world";
Map<Character, List<Integer>> letters = new HashMap<Character, List<Integer>>();
String string = input.replaceAll("\\s", "");
for (int i = 0; i < string.length(); i++) {
letters.merge(string.charAt(i), Arrays.asList(i), (o, n) ->
Stream.concat(o.stream(), n.stream()).collect(Collectors.toList()));
}
System.out.println(letters);
Essentially, this is what you want to do.
This presumes a HashMap<String, List<Integer>>
List<Integer> sCharIndex;
for (int i = 0; i < s.length(); i++) {
// get the character
char ch = s.charAt(i);
if (!Character.isLetter(ch)) {
// only check letters
continue;
}
ch = ch+""; // to string
// get the list for character
sCharIndex = sMap.get(ch);
// if it is null, create one and add it
if (sCharIndex == null) {
// create list
sCharIndex = new ArrayList<>();
// put list in map
sMap.put(ch, sCharIndex);
}
// at this point you have the list so
// add the index to it.
sCharIndex.add(i);
}
return sMap;
A hashMap is nothing more than a special data structure that takes an object as a key. Think of an array that takes a digit as an index and you can store anything there.
A hashMap can take anything as a key (like an index but it is called a key) and it can also store anything.
Note that your key to hashMap is a String but you're using a character which is not the same. So you need to decide which you want.
HashMap<String, List<Integer>> or HashMap<Character, List<Integer>>
There are also easier ways to do this but this is how most would accomplish this prior to Java 8.
Here is a much more compact way using streams. No loops required.
Map<String, List<Integer>> map2 = IntStream
.range(0,s.length())
// only look for letters.
.filter(i->Character.isLetter(s.charAt(i)))
.boxed()
// stream the Integers from 0 to length
// and group them by character in a list of indices.
.collect(Collectors.groupingBy(i->s.charAt(i)+""));
But I recommend you become familiar with the basics before delving into streams (or until your instructor recommends to do so).
For more information check out The Java Tutorials
Check out this code :
public static void main(String []args){
//Create map of respective keys and values
HashMap<Character, ArrayList<Integer>> map = new HashMap();
String str = "Hello world"; //test string
int length = str.length(); //length of string
for(int i = 0; i < length; i++){
ArrayList<Integer> indexes = new ArrayList(); //empty list of indexes
//character of test string at particular position
Character ch = str.charAt(i);
//if key is already present in the map, then add the previous index associated with the character to the indexes list
if(map.containsKey(ch)){
//adding previous indexes to the list
indexes.addAll(map.get(ch));
}
//add the current index of the character to the respective key in map
indexes.add(i);
//put the indexes in the map and map it to the current character
map.put(ch, indexes);
}
//print the indexes of 'l' character
System.out.print(map.get('l'));
}
The code is self explanatory.
public class Array {
public static void main(String[] args) {
printSortedMap(concordanceForString("Hello world")); // r[7] d[9] e[1] w[5] H[0] l[2, 3, 8] o[4, 6]
}
public static HashMap<String, ArrayList<Integer>> concordanceForString(String s) {
HashMap<String, ArrayList<Integer>> sMap = new HashMap<>();
String str = s.replace(" ", "");
for (int i = 0; i < str.length(); i++) {
ArrayList<Integer> sCharIndex = new ArrayList<Integer>();
for (int j = 0; j < str.length(); j++) {
if ( str.charAt(i) == str.charAt(j) ) {
sCharIndex.add(j);
}
}
sMap.put(str.substring(i,i+1), sCharIndex);
}
return sMap;
}
public static void printSortedMap(HashMap<String, ArrayList<Integer>> sMap) {
for (Map.Entry<String, ArrayList<Integer>> entry : sMap.entrySet()) {
System.out.println(entry.getKey() + entry.getValue());
}
}

Find the how much unique values in a list of vectors - Java

I have to write a code to parse a list of sublist and return how much unique values I have in each subList, I have written this code:
public static Map<Integer,Set<String>> findAllFrequencies(List<List<String>> data){
// main key is the column index
Map<Integer,Set<String>> frequency = new HashMap<>();
for (Integer i = 0; i < data.size(); i++) {
List<String> line = data.get(i);
for (String cell : line) {
frequency.putIfAbsent(i, Sets.newHashSet(cell));
frequency.computeIfPresent(i, (k, v) -> {
v.add(cell);
return v;
});
}
}
return frequency;
}
Assuming My input is a File and not a List of List is there a better solution?
The idea is to get a File and parse each columns and find total unique values per column.
You have several ways to know if a String is unique in a list of Strings.
1) The lazy solution : use Streams and compute a Map of occurrences of each String :
Map<String, Long> occurrences = strings.stream()
.collect(Collectors.groupingBy(s -> s, Collectors.counting()));
Then, each entry which has a value of 1 is unique.
2) Compute the duplicates and remove all duplicates from the original list :
Set<String> alreadySeen = new HashSet<>();
Set<String> duplicates = new HashSet<>();
for (String s : strings) {
if(alreadySeen.contains(s)) {
duplicates.add(s);
}
alreadySeen.add(s);
}
List<String> result = new ArrayList<>(strings)
result.removeAll(duplicates);
3) If you don't want to create intermediate collections, sort the List. Each element which is different from its predecessor and successor is unique (the cleanest one imho) :
Set<String> uniques = new HashSet<>();
strings.sort(Comparator.naturalOrder());
for(int i = 0; i< strings.size(); i++) {
String predecessor = i > 0 ? strings.get(i - 1) : null;
String successor = i < strings.size() - 1 ? strings.get(i + 1) : null;
String current = strings.get(i);
if(!current.equals(predecessor) && !current.equals(successor)) {
uniques.add(current);
}
}

why is map.get() function null?

My code iterates over a char array (char[] charArray), and finds for the key. The key is then used to find the value in a Map. However, the map.get() function is giving me a null even thought I set it as a value and i am not sure why. Thanks!
parameters for this method are:
LinkedBinaryTree<String> and HashMap<String, Integer>
for (int i = 0; i < charArray.length; i++) {
if (Character.isLetter(charArray[i])) {
// Why is map.get(charArray[i]) null??
String char2String = Character.toString(charArray[i]);
if (map.get(char2String) == null) {
throw new IllegalArgumentException("int is null");
}
int k = map.get(char2String);
charArray[i] = Integer.toString(k).charAt(0);
}
}
This is a testcase i wrote to test the method.
#Test
public void testSubstituteMap() {
LinkedBinaryTree<String> tree2 = Assignment.prefix2tree("- x + 1 + x x");
HashMap<String, Integer> Map = new HashMap<String, Integer>();
Map.put("x", 5);
tree2 = Assignment.substitute(tree2, Map);
LinkedBinaryTree<String> expected = Assignment.prefix2tree("- 5 + 1 + 5 5");
assertEquals(Assignment.tree2prefix(expected), Assignment.tree2prefix(tree2));
}
Which results in:
You are putting String keys and trying to get the same with a char key.
Note that in Java "x" is not equals to 'x'
You can either change your Map to char keys or use String array. Since they are single letters, I suggest to keep them with Char's.

How to get the positions of array duplicates JAVA

I currently have this code:
String foxes = "The,Quick,Brown,Fox,Jumped,Over,The,Lazy,Dog.";
System.out.println(" Here is the string unedited: " + foxes);
String lowerCase = foxes.toLowerCase() .replaceAll("[\.:;'\"!\?]", " ");
System.out.println(" Here is the string (no caps + no punctuation): " + lowerCase);
List<String> foxesList = new ArrayList<String>(Arrays.asList(lowerCase.split(",")));
In short this code creates a String, makes it non case sensitive and then converts it into an array.
I now need to find the positions of each of the duplicates in the array and I currently am aware that it has something to do with nested loops. The duplicates are The which occurs 2 times. I need to know the positions of these 2 duplicates.
You can use HashMap<String, int[]:
Map<String, ArrayList<Integer>> map = new HashMap<>();
for (int i = 0; i < foxesList.size(); i++) {
String fox = foxesList.get(i);
ArrayList<Integer> list = map.get(fox);
if (list == null) {
list = new ArrayList<>();
list.add(i);
map.put(fox, list);
} else {
list.add(i);
}
}
In this map for each fox name, you'll store all indexes of this fox. In case the list has more then one element, it means there is a duplicate.
Algo to find index of duplicate
Create an array of string ( by spliting input by " ")
Iterate over array and build a map of each array element to list of its position in the map.
3.Finally you have all info in map. For every entry you have index it occur. If it is more than 1 then it is duplicate and u have index
You can use :
HashMap(key: String, value: ArrayList)
to store the strings
where arraylist will store the corresponding indexes.
If value.size() > 1, it's keys occurrence > 1.
Code :
HashMap<String, ArrayList<Integer>> dictMap = new HashMap<String, ArrayList<Integer>>();
String strArr[]={"Hi", "Foo", "Bar", "Foo"};
for(int i = 0; i < strArr.length; i++){
String str = strArr[i];
if(dictMap.containsKey(str)){
ArrayList<Integer> al = dictMap.get(str);
al.add(i);
}
else{
ArrayList<Integer> al = new ArrayList<Integer>();
al.add(i);
dictMap.put(str, al);
}
}
There are already a few correct answers here, let me just give a slightly more concise one to create the map, assuming that you are using Java 8:
Map<String, List<Integer>> map = new HashMap<>();
for (int i = 0; i < foxesList.size(); i++) {
String fox = foxesList.get(i);
map.computeIfAbsent(fox, f -> new ArrayList<>()).add(i);
}
Using Map#computeIfAbsent allows to have just one line for both the case where you already have a list in the map and where you don't.

How do I compare 2 arraylists in a Hashmap?

I have an arraylist called fetchContactName() which returns all names (31) in my contact list, an arraylist called fetchContactNumbers() which returns all phone numbers (31) associated with fetchContactName(), and an arraylist called newList which has all the numbers that sent me text messages (6).
I was trying to change the phone numbers in newList by looking for the same numbers in fetchContactNumbers(). When there was a match, I would then index the position in fetchContactNumbers() and use that index to get the name at the same position in fetchContactName(). From there, I would replace the numbers in newList with the names in fetchContactName() according to the indexed position.
This is an example I've made that executes as stated above:
http://pastebin.com/pApHNkXa
The problem with the above example is that when I apply it to my listview, only one element in the list is changed to a name. More oddly, newList.get(3) is the only one that changed to a name. Not newList at positions 0, 1, 2, 4 and 5.
From others suggests, how can I use a HashMap to give the same expected result as the example given above? I was told to use fetchContactNumbers() and fetchContactNames() in the Hashmap then use the HashMap to compare with newList, but I cant find any source to achieve this.
UPDATE:
Here is the working code for my HashMap, but the results are still the same as above:
for (String str : fetchContactNames()) {
contactNameNew += str + " ";
}
for (String str2 : fetchContactNumbers()) {
contactNumberNew += str2 + " ";
}
//String to split
String temp[];
String temp2[];
String delimiter = " ";
temp = contactNameNew.split(delimiter);
temp2 = contactNumberNew.split(delimiter);
HashMap<String, String> contacts = new HashMap<String, String>();
contacts.put(contactNameNew, contactNumberNew);
for(int i = 0; i < fetchContactNames().size(); i++){
contacts.put(temp[i], temp2[i]);
}
Iterator<Entry<String, String>> iterator = contacts.entrySet().iterator();
while(iterator.hasNext()){
Entry<String, String> entry = iterator.next();
int position = getPosition(newlist, entry.getValue());
if (newlist.contains(entry.getValue())) {
newlist.set(position, entry.getKey());
}
}
I think it will be better if I changed your code and answered...
import java.util.ArrayList;
import java.util.HashMap;
public class StringT {
public static void main(String[] args) {
// alpha would represent fetchContactNames()
ArrayList<String> alpha = new ArrayList<String>();
// bravo would represent fetchContactNumbers()
HashMap<String, String> bravo = new HashMap<String, String>();
// charlie would represent newList
ArrayList<String> charlie = new ArrayList<String>();
bravo.put("1", "One"); charlie.add("5");
bravo.put("2", "Two"); charlie.add("1");
bravo.put("3", "Three"); charlie.add("3");
bravo.put("4", "Four"); charlie.add("4");
bravo.put("5", "Five"); charlie.add("2");
// this will print charlie just as you see above
for(int i = 0; i < charlie.size(); i ++){
System.out.println(charlie.get(i));
}
System.out.println("---------------------");
// this will print charlie with the numbers replaced as names
for(int i = 0; i < charlie.size(); i++){
String value;
if((value = bravo.get(charlie.get(i))) != null){
charlie.set(i, value);
}
}
for(int i = 0; i < charlie.size(); i ++){
System.out.println(charlie.get(i));
}
}
}
your code is working that u placed here http://pastebin.com/pApHNkXa i tried it in android and its working alright its giving output as five, two, seven, three .

Categories