Tree Data Structure in HashMap - java

I'm trying to create a tree structure based on a result set I get from a query. The below block of code works only if the result set has two columns. The first column is the parent and the second column is the child. Problem I'm running into is trying to re-engineer this so that it can incorporate multiple different levels (each column representing a level). Only way for me to do it now is to duplicate the code, check the number of levels and hard-coding to add in a new level. I'm processing the result set by row then column. (e.g. get the first row, then get the first column and store that value.)
Any idea on how I can re-engineer this functionality to be flexible on the number of levels it can go? Ultimately, the root gets passed into a HashTable and processed to a JSON file. FYI, I'm doing the JSON formatting in the second part of the code by traversing through the HashMap and formatting it to fit what I need for the JSON.
HashMap<String, HashSet<String>> level1TwoColumn = new HashMap<String, HashSet<String>>();
Object[] listElementCalcColumnNumber = list.get(0);
Hashtable allHash = new Hashtable();
//this will store all of the values in a hashmap and hashset
for(int i=0; i<list.size(); i++){
Object[] listElement = list.get(i);
//the reason we added ""+ between (String) and listElement is because listElement can be something other than a String (e.g. double, integer, etc)
//by adding "" to it, it becomes a String value automatically so then we can cast double/integer/etc into a String
String currentLevel1 = (String) ""+listElement[0];
currentLevel1 = currentLevel1.replace("\"", "");
//this prevents variables from duplicating. if the new element does not exist in hashmap, a new record in the hashmap will be created.
if((level1TwoColumn.get(currentLevel1) = null)){
HashSet<String> level2 = new HashSet<String>();
level1TwoColumn.put(currentLevel1, level2);
}
//stores all of the lowest level into a hashset because they're all going to be unique. no need to check to see if they exist in the hashset.
String currentLevel2 = (String) ""+listElement[1];
currentLevel2 = currentLevel2.replace("\"", "");
level1TwoColumn.get(currentLevel1).add(currentLevel2);
}
HashSet completeTree = new HashSet();
//now that the structure of the data is complete. iterate through level1 to get and store keys as values and "name" as key
for(String key1 : level1TwoColumn.keySet()){
HashSet levelOneSet = new HashSet();
HashMap levelOne = new HashMap();
levelOne.put("name", key1);
levelOneSet.add(levelOne);
//this for-statement does the same thing as previous for-statement; stores the unique values and give them "name" and then put them in hashset and give the set a "children" key
for(String key2 : level1TwoColumn.get(key1)){
HashSet levelTwoSet = new HashSet();
HashMap levelTwo = new HashMap();
levelTwo.put("name", key2);
levelTwoSet.add(levelTwo);
levelOne.put("children", levelTwoSet);
}
//once it loops through once, all level 2 items will be stored under a unique level 1. then it gets added into our dendrogram one by one until all level 1 elements are added.
completeTree.add(levelOne);
}
//this is assigning what our first node is, which is "VA"
allHash.put("name", "VA");
//put everything under "VA" node
allHash.put("children", completeTree);

Related

How to access a single ArrayList in ArrayListMultiMap

I would like to get an entry from ArrayList in an ArrayListMultiMap. I am using Google Guava ArrayListMultimap and each key is associated with multiple array lists. For example, for the key1 I have 4 array lists, and each ArrayList contains 2 entries. I need to be able to access a particular ArrayList and get an entry from there so my question is how do I do it? Every time I try to access the value associated with the key it prints all 4 array lists but I need only one.
Multimap<String, ArrayList<String>> wordAsKey = ArrayListMultimap.create();
for (DictionaryEntries dict : DictionaryEntries.values()) {
ArrayList<String> list = new ArrayList<>();
String key = dict.getKey();
String partOfSpeech = dict.getPartOfSpeech();
String definition = dict.getDefinition();
list.add(partOfSpeech);
list.add(definition);
wordAsKey.put(key, list);
}
ArrayList<String> resultList = new ArrayList<>();
resultList.add(wordAsKey.get(word).toString());
System.out.println(resultList);
Prints
[[[noun, A set of pages.], [noun, A written work published in printed or electronic form.], [verb, To arrange for someone to have a seat on a plane.], [verb, To arrange something on a particular date.]]]
But I need it to print only [noun, A set of pages.]
you can try: get index value
int index = 0;
resultList.add(wordAsKey.get(word).get(index).toString());
Just do it like this -
ArrayList<String> list = (ArrayList<String>)wordAsKey.get(word);
String result = list.get(index);
System.out.println(result);
And you can check whether particular String is exist or not in List, then see below;
if(list.contains("search")){...}

Remove entries from Java LinkedHashMap

I have to compare two Excel files (with different data) and create two new Excel tables:
Table 1 contains all matching entries
Table 2 contains all entries that not match
Therefore I iterate over both Excel files and store the matching entries in a LinkedHashMap. In a second LinkedHashMap I store all entries from the Excel file. With this two Maps I want to identify the delta.
To identify the delta I compare both lists and now want to remove all entries from the complete list, if the entry is already in the list with the matching ones.
I tried different solutions - all with the result that the code is running but never an entry is really removed. Can anyone help please?
Heres my code:
// This code fills both Maps
LinkedHashMap<String, String> liste_matches = new LinkedHashMap<String, String> ();
LinkedHashMap<String, String> liste_complete = new LinkedHashMap<String, String> ();
while(worksheet1.getLastRowNum() >= j){
liste_complete.put(String.valueOf(worksheet1.getRow(j).getCell(18)), "");
// Counter for loop, loops trough Telekom datasets
int i = 1;
while(worksheet2.getLastRowNum() >= i)
{
if(String.valueOf(worksheet1.getRow(j).getCell(18)).equals(String.valueOf(worksheet2.getRow(i).getCell(9))))
{
if(!liste_matches.containsKey(String.valueOf(worksheet1.getRow(j).getCell(18)))){
liste_matches.put(String.valueOf(worksheet1.getRow(j).getCell(18)), "");
}
}
}
// build Excel table
}
This is my code I used to compare both lists and remove all entries from liste_complete that are already in liste_matches.
I first tried this (I inserted the ArrayList for my second try...). It's running but without any effect to the list.
ArrayList list = new ArrayList();
for(Map.Entry<String,String> keyDelta : liste_complete.entrySet())
{
for(Map.Entry<String,String> key : liste_matches.entrySet()){
if(keyDelta.equals(key)){
liste_complete.remove(keyDelta);
list.add(entry.getValue());
}
}
}
Afterwards I tried this but also without any effect to the List:
for(int c = 0; c < list.size(); c++)
{
String str = list.get(c);
liste_complete.remove(str);
}
I found this solution in StackOverflow, but that returns java.lang.IllegalStateException
Iterator<Map.Entry<String,String>> iter = liste_complete.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<String,String> entry = iter.next();
for(Map.Entry<String,String> key : liste_matches.entrySet()){
if(key.getValue().equalsIgnoreCase(entry.getValue())){
iter.remove();
}
}
}
AFAIK you can't remove element from a list you're iterating on.
I suggest you 2 solutions:
iterate on your lists to check for matching keys and store the match in the third list; then iterate on the third list and remove from liste_complete
refactor the first piece of code of your question so that you store in one list the matching values and in the other the non-matching. Pseudo code could be:
for worksheet1 row
for worksheet2 row
if(match)
liste_matches.add(...)
else
liste_non_matches.add(...)
In this way you do not have to remove elements afterwards.
Thanks a lot for your hints.
I already debugged the code but didn't understand the problem - I think it really was a problem of the complex input data.
I did not compare the keys via key.getKey() but only with key and that seems to cause problems in the comparison. Anyway, my code runs with this snippet:
for(Map.Entry<String,String> keyDelta : liste_Complete.entrySet()){
if(!liste.containsKey(keyDelta.getKey())){
delta_liste.put(String.valueOf(keyDelta), "");
}
}

Merging n number of list into a Map based on a value in List

I have the following objects in an ArrayList and a value in this object is illustrated as the numbers at the beginning, which are Id of something.
I need to create a Map object, whose key should be the id of objects and whose values should be the objects with id. At the end of the day, I would like to have a Map something like that.
I have already solved this problem with two for loops and lots of if statements but it seems very ugly to me.
Any cleaner solution would be appreciated.
Map<Integer, List<Foo>> result = list.stream().collect(Collectors.groupingBy(Foo::getId));
Edited to fit the question edit, it is as simple as this:
ArrayList<Element> list = ...;
HashMap<Integer, List<Element>> map = new HashMap<Integer, List<Element>>();
for(Element e : list) {
ArrayList<Element> auxList;
if(map.contains(e.getId()) {
auxList = map.get(e.getId());
} else {
auxList = new ArrayList<Element>();
map.put(e.getId(), auxList);
}
auxList.add(e);
}
Just iterate over the starting list and add the elements to the map. If the map already contains the id, add it to the list. If not, create a new list.

Complex Hashmap ArrayList Generator

Here's some code:
ArrayList<String> List = new ArrayList<>();
Map<String, List<String> > map = new HashMap<String, List<String>>();
List.add("stringA");
List.add("stringB");
List.add("stringC");
for(int i = 0; i<List.size();i++){
String key = List.get(i);
List<String> value = new ArrayList<String>();
map.put(key, value);
}
This code takes whatever is in the ArrayList, loops through it, adds it to the Map, and then creates an empty ArrayList with each string name as the variable name. Now, this works, but there's one problem, unless I'm overlooking something. At some point, I will need to access the new empty ArrayLists that are in the map. However, I won't know what the titles of these ArrayLists are, without printing them out, which I don't want to do. Basically, I'm thinking I need a map method or class and then an additional map key method or class. I'm not sure how to implement it but maybe something like this:
public class MapKey {
public MapKey(int count, String header){
}
}
Map<MapKey, List<String> > map = new HashMap<MapKey, List<String>>();
Another option I've considered is to somehow loop through the map array and add Strings to each ArrayList, but I'm very new to maps and looping through them. Especially ones that contain ArrayLists as their values.
There're multiple ways to access keys and values of your HashMap:
for (Map.Entry<String,ArrayList<String>> entry : map.entrySet()) {
String key = entry.getKey();
ArrayList<String> value = entry.getValue();
// do your work
}
or
Set<String> keys = map.keySet();
for(String key : keys){
ArrayList<String> value = map.get(key);
}
Read the java HashMap api Java HashMap Link
Edit:
you dont need to loop through your outside ArrayList objects when you add all of its elements to another, just simply invoke addAll(), it will append all elements of an arraylist to another.
ArrayList<String> aList = map.get("stringA");
assume your first outside ArrayList is called outListOne;
aList.addAll(outListOne);
Appends to corresponding lists:
//assume number of outside lists are equal to number of map elements
String[] keysArr = {"stringA", "stringB", "stringC"};
ArrayList[] outLists = {outListOne, outListTwo, outListThree};
// adds outside lists to corresponding map ArrayList lists
for(int i = 0; i < keysArr.length; i++){
list = map.get(keysArr[i]); // you ArrayList in a map, get it by key name
list.addAll(outLists[i]); // append elements from out list to corresponding list
}
Not exactly sure what you mean by "titles of these ArrayLists." But here are a few code snippets that might give you a better idea of how to work with your map:
// add string x to the list for "stringA"
map.get("stringA").add(x);
// print all the values in the list for "stringC"
for (String s: map.get("stringC")) {
System.out.println(s);
}
// print the names of the lists that contain "xyzzy"
for (String key: map.keySet()) {
if (map.get(key).contains("xyzzy")) {
System.out.println(key);
}
}
// remove "foo" wherever it appears in any of the lists
for (List<String> list: map.values()) {
while (list.remove("foo")){}
}

Remove last element from HashMap

I am trying to remove last element from
Map<String, List<String>> map = new HashMap<String, List<String>>();
My code is
StringTokenizer stheader = new StringTokenizer(value.toString(),",");
while (stheader.hasMoreTokens()){
String tmp = stheader.nextToken();
header.add(tmp);
System.out.println("tmp"+header);
map.put(tmp, new ArrayList<String>());
}
System.out.println(map.size());
Output:
tmp[Sepal_Length, Sepal_Width, Petal_Length, Petal_Width, Class]
map{Petal_Width=[], Class=[], Petal_Length=[], Sepal_Length=[], Sepal_Width=[]}
I want to remove the key Class[] from map or tmp.
I tried using .remove() but nothing is reflecting.
There is no order in HashMap, so, you can't remove the last item. Use LinkedHashMap to have the order of insertion.
You have two collections effectively, so if you want the "Class" element removed, you need to do it in both. If always removing the last element of tmp in both collections is what you care about, and assuming header is a List<String>, you should do something like this:
String keyToRemove = header.remove(header.size()-1);
map.remove(keyToRemove);
#Unmesha SreeVeni : Use LinkedHashMap to delete last element because HashMap does not maintain order of insertion of the elements.
HashMap doesn't arrange it's elements according to an index, but you can retrieve only the element according to it's key, so if you have to use a HashMap you have to add an incremental index to it's key, so when you put a new element that index incremented with one and put with the key in the HashMap, like this :
Map<Map<int,String>, List<String>> map = new HashMap<Map<int,String>, List<String>>();
int index = 0;
StringTokenizer stheader = new StringTokenizer(value.toString(),",");
while (stheader.hasMoreTokens()){
String tmp = stheader.nextToken();
header.add(tmp);
System.out.println("tmp"+header);
Map<int, String> temp_map = new HashMap<int, String>();
temp_map.put(index, tmp);
index ++;
map.put(temp_map, new ArrayList<String>());
}
and then you can check the value of index in the end and that will be the index of the last element.

Categories