Recommend Data structure? multi-map?
Hello everyone.
I'm not sure what data structure I should use for my particular problem.This is whats going to be happening.
I'm writing a SocketServer, its going to be receiving 1000's of strings of random length. Each string is going to have an integer which can be any number, for instance (240). I'm going to parse out that number and it will be the Entity ID. The rest of the string is going to be stored as an "Alert".
So for instance:
Incoming string #1:240 opie.tivlab.raleigh.ibm.com went down at 12:40pm.
Incoming string#2:241 baleve.tivlab.raleigh.ibm.com went down at 4:00pm.
Incoming string#3:240 Error 309830
Incoming string#4:444 Error 20393
The numbers 240, and 241, and 444 are the entityID's.
I want to group the Strings with the EntityID's for instance
I want a list of all the Messages(strings) that had the entityID 240.
so:
if I accessed EntityID 240, I would find the following strings:
EntityID = 240:
1. opie.tivlab.raleigh.ibm.com went down at 12:40pm.
2. Error 309830
If I accessed EntityID 444 I would have:
EntityID = 444
1. Error 20393
I know a map has key/value pairs, can I use the entity ID as the key, and the value's being the rest of the string?
Is what I'm looking for a multimap? can I have 1 key, and have it mapped to several different strings?
Thanks guys!
[1440 byte] By [
lokiea] at [2007-11-15]

A Map with the entity ID as key and a collection of Strings as value? The collection could be ArrayList or something else depending on your requirements.Message was edited by: OleVV
Thanks for the response.
I was looking at the Java site here:
http://java.sun.com/docs/books/tutorial/collections/interfaces/map.html
and It looks like I can't use just a regular map like this can I?
Map<int,List><String>> Alert = new Map<int,List><String>>();?
But they showed this:
Map<int, List><String>> m
= new HashMap<int, List><String>>();
Message was edited by:
lokie
Message was edited by:
lokie
You cannot use int, but Integer or better Long, depending on the range of numbers. I.e. Map< Long, List<String> >
Oh yah! Sorry I'm still learning Java. I've been using C++ for awhile so it will take awhile to break that habit.
So do I need a mutli map or can I just use a map?
I know a map is defiend as linking 1 KEY to exactly 1 VALUE. But does Java know that
Map<Integer, List><String>> m = new HashMap<Integer,List><String>>();
value is a Linked List of Strings? Or does it consider the container List, as 1 value?
I also noticed, they arn't saying:
Map<Integer, List><String>> m = new Map<Integer,List><String>>();
Do you always have to say HashMap, and you can't use Map?
Thanks!
Your code should become somewhat like the following:
Map< Integer, List<String> > m = new HashMap< Integer, List<String> >();
...
List<String> lst = m.get(someId);
if (lst == null) {
lst = new ArrayList<String>();
m.put(someId, lst);
}
lst.add(message);
Map and List only are interfaces, where HashMap and ArrayList are implementations of these. There are more implementations available in the collections framework of Java and it depends on your goals, which you take.
The above code includes the creation of a Map that contains lists as values. No List is created at this point!
It further shows how to take the according list from the map that is stored for a specific id or create a new list if none is stored, respectively. Once you have the list, you can add the message. That is, you will have to add a new list object for each id coming in or pick the list to add new messages, if the id has already been treated.
Hope, this is not too confusing an explanation :)
Ahh Excellent example, i'm studying it right now and I have a few questions!
Here is your code:
Map< Integer, List<String> > m = new HashMap< Integer, List<String> >();
...
List<String> lst = m.get(someId);
if (lst == null) {
lst = new ArrayList<String>();
m.put(someId, lst);
}
lst.add(message);
When you say:
List<String>lst = m.get(someId);
I see the interface for Map is:
public interface Map<K,V> {
// Basic operations
V put(K key, V value);
V get(Object key);
Is that "someID" refering to the Integer of the Map? Map<Integer,List><String>> ?
And the return value for that the List object?
So when you assign the return value of m.get(someID) I'm not sure how List<String> lst is processing it.
So if I had the EnityID being 244 and the string is: "server crash".
and I want to place 244 as the "key" for the map, and "server crash" as the first entry in the List<String>
would I do:
Map< Integer, List<String> > m = new HashMap< Integer, List<String> >();
...
String Message = "This server crashed";
List<String> lst = m.get(244);
if (lst == null) {
lst = new ArrayList<String>();
[b] list.add(Message);[/b]
m.put(244, lst);
}
Thanks!
Message was edited by:
lokie
null
Message was edited by:
lokie
Typo
> When you say:
> > List<String>lst = m.get(someId);
>
> (...)
> Is that "someID" refering to the Integer of the Map?
Yes.
> Map<Integer,List><String>> ?
> nd the return value for that the List object?
Yes.
> So when you assign the return value of m.get(someID)
> I'm not sure how List<String> lst is processing it.
I am not sure what you mean with processing?
The variable lst will hold a reference to the list stored in the map.
> would I do:
> > Map< Integer, List<String> > m = new HashMap<
> Integer, List<String> >();
> ...
> String Message = "This server crashed";
> List<String> lst = m.get(244);
> if (lst == null) {
>lst = new ArrayList<String>();
> b] list.add(Message);[/b]
>m.put(244, lst);
>
>
Somewhat like that, yes. Of course, you would have the number stored in variable and not hard coded, wouldn't you? And the list.add should be outside the if statement, which only is here to create a new list in case there is no list yet for 244.
I think, the most important information is that you always deal with references to objects and not with objects. So you do not have to put the list back into the map each time, but may use the one you get from the list.
Thanks the the help its going pretty good now that you started me out.
The problem i'm having now is printing out the Key along with all the messages...
It skips the first element but everything else is working!
Because Maps don't support iterators I soon found out, I put all the keys in a set which does support iteerators...here is my code:
package alert;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.ArrayList;
import java.util.Set;
import java.util.Iterator;
public class Message {
Integer entityID;
String message;
//constructor
Message(Integer entityID, String message)
{
this.entityID = entityID;
this.message = message;
}
//no param construct
Message()
{
entityID = new Integer(0);
message = "";
}
//print******ISSUE IS IN HERE*********-
void print(Map<Integer, List><String> > hashM)
{
//want to print out the Key and all the Messages
//associated with that key
Set keys = hashM.keySet();// The set of keys in the map.
Iterator keyIter = keys.iterator();
System.out.println("The map contains the following associations:");
while (keyIter.hasNext()) {
Object key = keyIter.next(); // Get the next key.
Object value = hashM.get(key); // Get the value for that key.
System.out.println( "(" + key + "," + value + ")" );
}
}
void Input(Map<Integer, List><String>> mapAlert, Integer entityID, String msg)
{
//getting the position of the List by EntityID if avaiable
List<String> Alert = mapAlert.get(entityID);
//checking to see if there is a unique Key already in the Map.
if (Alert == null)
{
//if there isnt a key in the map, add a new key, and a new List mapping
//to the key EntityID;
Alert = new ArrayList<String>();
mapAlert.put(entityID, Alert);
}
else
{
//adding message to List
Alert.add(msg);
}
}
}
//-Main function
package alert;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
public class Alert {
public static void main(String [] args)
{
Map<Integer, List><String>> AlertMap = new HashMap<Integer, List><String>>();
String message = "This is a test1";
String message2 = "This is another test2";
String message3 = "This is another test3";
String message4 = "This is for key(222) test1";
String message5 = "This is for key(222) test2";
String message6 = "This is for key(222) test3";
Integer entityID = new Integer(333);
Integer entityID2 = new Integer(222);
Message testMessage = new Message();
//manually inserting strings into Map.
//For ID: 333
testMessage.Input(AlertMap,entityID, message);
testMessage.Input(AlertMap,entityID, message2);
testMessage.Input(AlertMap,entityID, message3);
//For ID: 222
testMessage.Input(AlertMap,entityID2, message4);
testMessage.Input(AlertMap,entityID2, message5);
testMessage.Input(AlertMap,entityID2, message6);
testMessage.print(AlertMap);
}
}
//OUTPUT:
The map contains the following associations:
(222,[This is for key(222) test2, This is for key(222) test3])
(333,[This is another test2, This is another test3])
N/M I fixed it!During the Add function I added an if() else, in the if I should have also added the new string, after creating the new list! it works great now!XD
That's why I said to put the add outside the if ;)
Btw., for looping on a Map you can use different approaches. As you recognized, the map gives you a reference to the key's set. It also gives you a handle on the set of entries, which allows you to use the for-each loop instead iterators (like does the key's set):for (Map.Entry< Integer, List<String> > entry : map.entrySet()) {
Integer id = entry.getKey();
List<String> msgs = entry.getValue();
...
}
Further, you should also loop over the messages to print them, rather than printing the List directly. And, when you definitely want to use the iterator, you should use it generic as Iterator<Integer>. And, when getting the value from the map, you have definitely more information on it than it being an Object.
Good luck.
Your way is alot nicer than mine :D
Hm...i'm not sure how else I would print out the contents of the list without just using how I did it...
Do you know off hand how I can print the messages, rather than the list directly?
Maybe that will also fix my formatting issue i'm running into, its printing the contents of the map like this:
Entity ID: 333
[message1,message2....,...message x]
> Hm...i'm not sure how else I would print out the
> contents of the list without just using how I did
> it...
> Do you know off hand how I can print the messages,
> rather than the list directly?
Erm ... you could loop over the list and print each entry?