Create Multidimensional HashMap in java - java

I am kind of new to java, I have this code
...
NodeList indexEntryList = sourceDoc.getElementsByTagName("in.ar"); //this is a xml tag
for (int i = 0; i < indexEntryList.getLength(); i++) {
...
}
...
I have to create a HashMap (or something like this), where I save a String which is an attribute of the node, and a List of all nodes that have the same attribute.
I think something like this:
Map<String, ArrayList<Node>> indexCategories = new HashMap<String, ArrayList<Node>>();
But in each time of the for, I dont know how to search in all keys of the Map, and add the new Node to the list, and if the key does no exists yet, create the new item inside the Map.

Use Map#containsKey() for searching if a key is present, Map#get() for obtaining the collection (if present) respective Map#put() for storing the newly created map. Everything could be found properly documented in the Map API, by the way.

If you look at NodeList's documentation, you'll see that it has only two methods: getLength() (which you've used) and Node item(int index).
So your loop will be:
for (int i = 0; i < indexEntryList.getLength(); i++) {
Node node = indexEntryList.item(i);
// do something with node
}
... and what you want to do with node, is find its attributes.
NamedNodeMap attributes = node.getAttributes();
if(attributes != null) {
for(int j=0;j < attributes.getLength(); j++) {
Node attribute = attributes.item(j);
// do something with node and attribute
}
}
... so what do you want to do with your attribute and its node? I'm not sure, but I think your intent is that map.get(attributeName) returns a list of nodes containing that element.
If so:
// get the list for this element, or create one
List list = map.get(attribute.getName());
if(list == null) {
list = new ArrayList();
map.put(attribute.getName(), list);
}
// add the node we're working with to that list
list.add(node);
A few notes here:
you might be better off with a Set than a List, because you could end up adding the same node to a list many times.
I really recommend putting each of these blocks into a separate method, calling one from the other -- that is, where I've put do something..., have a method call. That gives you smaller chunks of code that are easier to understand and easier to test; it would also mean that you could call the loop counter 'i' in both 'for' loops.

Try this one...
Map<String, ArrayList<Node>> indexCategories = new HashMap<String, ArrayList<Node>>();
public void addNode(string key, Node node) {
List<Node> nodes;
if(indexCategories.containsKey(key)) {
nodes = indexCategories.get(key);
}
else {
nodes = new ArrayList<Node>();
}
nodes.add(node);
indexCategories.put(key, node);
}

You can use something like:
String key = nodeAttribute;
if (!indexCategories.containsKey(key)) {
indexCategories.put(key, new ArrayList<Node>());
}
indexCategories.get(key).add(node);

YOu might try something like this
NodeList indexEntryList = sourceDoc.getElementsByTagName("in.ar"); //this is a xml tag
for (int i = 0; i < indexEntryList.getLength(); i++) {
Node oneItem = indexEntryList.item(i);
String someString = "xxx or however you obtain the string";
ArrayList<Node> listOfNodes = indexCategories.get(someString);
if (listOfNodes == null) {
listOfNodes = new ArrayList<Node>();
}
listOfNodes.add(oneItem);
}

Related

Add a list into a BinarySearchTree <Integer, List<Object>>

I'm new in Java and I want to add a list into a BinarySearchTree with an Integer as a Key and a List as value.
So I need every element of a list that I want to add and add to the BST.
I'm using BST because I need to sort it with the key.
In the class Group I have a method called getNumber() that return the number os elements in the that group and the key will be the number of elements of a Group.
Right now I have this and I don't know how to continue. groups.iterator() is just to iterate every group of a list.
orderedGroups is a BinarySearchTree <Integer, List<Group>>().
EDIT:
I have this.
public Iterator<Entry<Integer, List<Group>>> listWarriors() throws NoGroupsException {
if(!isThereGroup())
throw new NoGroupsException();
Iterator<Entry<String, Group>> it = groups.iterator();
List<Group> listGroup = new DoublyLinkedList<Group>();
int j = 0;
while(it.hasNext()) {
listGroup.add(j, it.next().getValue());
j++;
}
for(int i = 0; i<j; i++) {
List<Group> list = orderedGroups.find(listGroup.get(i).getNumber());
if(list == null) {
list = new DoublyLinkedList<Group>();
list.addFirst(listGroup.get(i));
orderedGroups.insert(-(listGroup.get(i).getNumber()), list);
}
else {
if(list.equals(listGroup.get(i))) {
list.addFirst(listGroup.get(i));
}
}
}
return orderedGroups.iterator();
}
OrderedDictionary > orderedGroups = new BinarySearchTree>();
And a group is added by doing this.
public void addGroup(String idGrupo, String nome) throws GroupAlreadyExistsException {
if(searchGroup(idGrupo))
throw new GroupAlreadyExistsException();
group = new GroupClass(idGrupo, nome);
groups.insert(idGrupo.toLowerCase(), group);
}
I have all these in a Class called System.
It looks like you think you have to roll your own iterator in order to enumerate your list. Not necessary.
I can't tell exactly what you are trying to do here, but maybe the below will help, which just demonstrates how to iterate a list.
void addListToGroup(List<Foo> myList, List<group> myGroups) {
for (Foo foo : myList) {
Object value=myList.someFunction();
Group newGroup = new Group(value);
myGroups.add(newGroup);
}
}
I'm not sure I understand fully what you're trying to do, and why you're not using LinkedList and TreeMap, but I see a few issues in your code:
your for loop makes i start at 1 whereas list indices start at 0,
building listGroup seems useless: you could directly build orderedGroups
orderedGroups is not modified in your code (orderedGroupsByC is though)
UPDATE:
What if you did this:
Iterator<Entry<String, Group>> it = groups.iterator();
while (it.hasNext()) {
Group group = it.next();
List<Group> list = orderedGroups.find(group.getNumber());
if (list == null) {
list = new DoublyLinkedList<Group>();
list.addFirst(group);
orderedGroups.insert(group.getNumber(), list);
} else {
list.addFirst(group);
}
}

Bubble Sort Doubly Linked List Java

I am trying to create a bubble sort on a doubly linked linked list in Java but am getting Null Pointer Exception errors. I believe it to have an issue with when I call the getPrevious method on the head which of course has a value of null. However, I cannot think how to do the bubble sort without accessing the getPrevious method for the other nodes.
I can implement an if statement to check if its the head or tail of the list first, but I feel like there is a smarter way to do this.
I also have been unable to run a successful build of this, so am not even sure the code will work. If you have a different idea of how to implement this please let me know.
Any suggestions are welcome!
public static void bubbleSort(DoubleLinkedList list) //static method used to sort the linked list using bubble sort
{
int i = 0;
int j = 0;
Node currentNode = list.head;
Node previousNode = currentNode;
Node tempNext = currentNode;
Node tempPrevious = currentNode;
for(i=0; i<list.getSize(); i++)
{
for(j=0; j<list.getSize()-1; i++)
{
if(currentNode.getData() > currentNode.getNext().getData())
{
tempNext = currentNode.getNext().getNext();
tempPrevious = currentNode.getPrevious();
currentNode.getPrevious().setNext(currentNode.getNext());
currentNode.getNext().setNext(currentNode);
currentNode.setPrevious(currentNode.getNext());
currentNode.setNext(tempNext);
}
currentNode = currentNode.getNext();
}
}
}
So you have a double linked list. I assume each element contains some information... say an integer. It must also contain two pointers: one to the previous element and one to the next element.
Assuming this is true, notice that you don't have to modify the pointers because they already point from one element to another. all you have to do is sort the values of the list elements so that the first item in the list has the lowest value, the second has the second lowest value and so on.
You can do it like this:
public static void bubbleSort(DoubleLinkedList list) //static method used to sort the linked list using bubble sort {
int i = 0;
Node currentNode = list.head;
Node auxNode;
int foundChange = 1;
while(foundChange) {
foundChange = 0;
for(i=0; i<list.getSize()-1; i++) {
if (currentNode.getData() > currentNode.getNext().getData()) {
auxNode.setData(currentNode.getData());
currentNode.setData(currentNode.getNext.getData());
currentNode.getNext.setData(auxNode.getData());
foundChange = 1;
}
currentNode = currentNode.getNext();
}
}
If you haven't defined the setData method yet, then do so. It must be similar to getData, but it will set the data of an object to the value it gets as a parameter instead of returning the value of the data in that object.

Can you help me create a method that will return an entire Linked list and Queue-array;

As of now this is the method I have for my Queue,
public String rQueue()
{
for(int i = 0; i < queueName.length; i++)
return queueName[i];
return
" ";
}
The problem here is that the i++ is never reached because the queueName[i] is returned, when I use this method, only the first one is returned, and I can see why. How can I fix it so that I can return the entire contents of the queue.
I am also confused on the linked list, I have a linked list of an Object(). I only want to return Object.getMethod(); for every instance of each link. So this is what I have. The only way I can think of doing it is with another loop and to look at each spot, but I don't know how to return something like that.
public String displayLink()
{
Link current = first;
while(current != null)
{
current.displayMethod();
current = current.next;
}
}
I am really more stuck on the linked list, and the queue is just sort of a technical problem.
If you want to return a concatenation you could do something like:
public String rQueue() {
String r = "";
for(int i = 0; i < queueName.length; i++) {
if (i != 0) {
r += ", ";
}
r += queueName[i];
}
return r;
}
For the linked list you can return a collection. If displayMethod returns string, you could do something like:
public Collection<String> displayLink() {
Collection<String> result = new List<String>();
Link current = first;
while(current != null) {
result.add(current.displayMethod());
current = current.next;
}
return result;
}
First part,
public String[] qQueue { return queueName; } // or defensively copy, if you prefer
Then you have the array as the queue contents, if that's how it fits into the rest of your code.
Second part looks just fine to me.
What you are doing with the Linked List is actually the only way to traverse it (assuming it is a simple linked list with links from one node to the next). This is also why retrieving an element from a linked list is an O(n) operation, since you have to traverse the list to find the object you are looking for.
Now as far as returning the values is concerned you can just append them to a String and return this String in the end. Something like this would work:
public String rQueue() {
StringBuffer sb = new StringBuffer();
for(int i = 0; i < queueName.length; i++)
sb = sb.append(queueName[i]);
return sb.toString();
}
Note that I am using a StringBuffer in the above code since it is more efficient than concatenating to the end of a String, especially for a large number of concatenations.

Implementing my own HashSet class... my add() logic seems faulty

when scanning a file for words and using the built-in hashset class from the API, my word count returns 349 (which is what it's supposed to be)
Using my home-made hashset class, I get 235... so something in my add() method must be wrong, but I can't understand what it is.
thanks for any help!
public class HashWordSet implements WordSet {
private int size = 0;
private Node[] buckets = new Node[8];
public Iterator<Word> iterator() {
return new WordIterator();
}
//Add word if not already added
public void add(Word word) {
int key = getBucketNumber(word);
Node node = buckets[key];
while (node != null) {
if (node.value.equals(word))
return;
else
node = node.next;
}
node = new Node(word);
buckets[key] = node;
size++;
if (size == buckets.length) rehash();
}
private int getBucketNumber(Word word) {
int hc = word.hashCode();
if (hc < 0) hc = -hc;
return hc % buckets.length;
}
It seems like you override nodes[key] with the new word [only] instead of appending a new node to the list, so you lose all old data that was already in this node.
It should work fine if there are no elements in there before add() was invoked, but if there are - you will lose some data.
node = new Node(word);
buckets[key] = node;
Though it is hard to be 100% sure about it without the actual implementation of Node.
node = new Node(word);
buckets[key] = node;
If there are any nodes already in the bucket you have just thrown them away. Try something like:
node = new Node(word);
node.next = buckets[key];
buckets[key] = node;

Traversing a deep data structure & deleting object

I have a function to traverse a complex deep HashMap structure. My problem is that when I find the desired node, and do any action on it, such as deleting it, I'm not actually doing any action on the data structure, but instead I'm operating on a copy of the data structure. I'd think a pointer such as in C++ would solve my problem, so how can I do this in Java?
The code:
private HashMap parentNode = null;
// a complex JSON string of arrays / objects, won't list for brevity
private String jsonString = ...
// parses JSON string into HashMaps for objects and Object[ ]s for arrays
private HashMap arr = (HashMap)JSON.parse(jsonString);
// find the node with an id of 27
HashMap parent = findNode(arr, "27");
// Print arr before modifying node
System.out.println(arr);
// modify parent in some way
parent = null;
// Print arr after modifying node
System.out.println(arr);
public HashMap findNode(HashMap map, String id) {
parentNode = null;
findNodeRecursive(map, id);
return parentNode;
}
public void findNodeRecursive(HashMap map, String id) {
for(Object entry : map.entrySet()){
Object value = ((Map.Entry)entry).getValue();
if((value instanceof String) && ((String)value).equals(id))
parentNode = map;
else if(value instanceof HashMap)
findNodeRecursive((HashMap)value,id);
else if(value instanceof Object[])
for(int i=0; i<((Object[])value).length; i++)
findNodeRecursive( (HashMap)(((Object[])value)[i]) ,id);
}
}
To delete the node you want (parent), change your
parent = null;
to
arr.remove(parent);
Setting it to null does not delete anything, simply changes the reference that once was pointing to the node, back to null. To delete, you need to do it explicitly by using the HashMap.remove() method

Categories