2

I'm working on a chat server, and I'm putting the Clients into a Hashtable. This Hashtable is composed by <String name, Connection c>, where Connection has Socket and in-out flows.

I can send messages just looking for a nick in the Hashtable, but how can I send it to all the people?

Can I "Scout" (this was the unknown term) every Hashtable's entry? (like an array, I want to "SCOUT" each entry, so I'll do a loop and I'll send the message to everyone).

Thanks in advance.

ob_dev
  • 2,808
  • 1
  • 20
  • 26
Thorba
  • 181
  • 1
  • 11

4 Answers4

4

You could answer to your own question by reading the javadocs for HashMap. "Read the javadocs" is an important lesson that every beginner in Java should learn and remember.

In this case, the javadocs will show you 3 methods that could be useful:

  • The keys() method returns a collection consisting of the keys in the table.
  • The values() method returns a collection consisting of the values in the table.
  • The entries() method returns a collection representing the key/value pairs in the table.

You can iterate these collections as any other collection. There are examples in the other answers.


However, I get the impression that your application is multi-threaded. If that is the case the there are two other problems that you need to deal with to make your program reliable:

  1. If two or more threads could use the same object or data structure, they need to take the necessary steps to ensure that they are properly synchronized. If they don't then there is a non-zero probability that some sequence of operations will result in the data structure being put into an inconsistent state, or that one or more threads will see an inconsistent state (due to memory caches, values saved in registers, etc).

  2. If one thread is using one of a HashMap's collection iterators and another adds or removes an entry, then the first one is likely to get a ConcurrentModificationException.

  3. If you solve the above two problems by locking out all other operations on the HashMap while your "send to all" operation is going on, you are unintentionally creating a performance bottleneck. Basically, everything else stops until the operation has finished. You get a similar effect (but on a finer scale) if you simply put a synchronization wrapper around the HashMap.

You need to read and learn about these things. (And there's far too much to explain in a single SO Answer). A simple (but not universal) solution to all 3 problems that probably will work in your use-case it to use a ConcurrentHashMap instead of a plain HashMap.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • Damn, this is my first year with JAVA and second with English, and I'm a little bit lost. Anyways, thanks for your tips. I'll consider it how I can tomorrow, now is quite late in my country :P Thanks for your API tip. Anyways, is my first project so it shouldn't be complex. – Thorba Dec 31 '11 at 01:27
3

I can send messages just looking for a nick in the Hashtable, but how can I send it to all the people?

Then do the same for all nicknames in the hash table:

for (String name : yourTable.keySet())
    yourTable.get(name).send("your message");

or, alternatively:

for (Connection conn : yourTable.values())
    conn.send("your message");
aioobe
  • 413,195
  • 112
  • 811
  • 826
  • I believe the second option is what the OP asked for. The first option is slightly flawed. You should actually get the entrySet() and iterate over those, as it's more efficient than iterating keys and then calling get each time. FindBugs and Lint both mark that as a coding issue. – rfeak Dec 31 '11 at 00:46
  • 1
    Method 2 is more *efficient* assuming you don't need to use the `name` for anything. I wouldn't call the approach flawed or bugged though, regardless what some third party website said. – Perception Dec 31 '11 at 00:48
  • I formulated the answer as I did because of the OPs explicit formulation that he knew how to send the message to a given nick-name. (I just gave him a way to iterate over all nicknames.) Who knows, the actual message format may depend on the destination nick-name. – aioobe Dec 31 '11 at 00:52
  • You're welcome :-) I've never heard that term before. I think the correct terminology is "iterate over the hashtable", or "find all entries". :-) – aioobe Dec 31 '11 at 01:04
  • 1
    @StephenC - well, it's also homework. I'm not sure it's an appropriate juncture to drop those topics on the OP. He's still picking up the basics. – Perception Dec 31 '11 at 01:55
  • 1
    @Perception - if you call `entrySet` and iterate over that, you will get entries that also contain the name - so it's better because of the efficiency and identical features otherwise (but I would not call it flawed either, slightly flawed? hmmm, only because findbugs & lint pick it up) – Maarten Bodewes Dec 31 '11 at 02:24
  • @Perception - Hmm. Apparently trying to be polite has caused a failure in communication. Let me clarify. IF the OP needs both the key and the value, then the correct way to do it is to use entrySet(). Iterating over the keySet() and then calling get() on each of the keys is bad/wrong. I should NOT be done. Period. – rfeak Dec 31 '11 at 04:19
  • @Perception - I am assuming that if the OP is building chat server (homework or not) it will be multi-threaded. If he is writing multi-threaded applications, he *needs* to understand the issues. (And his instructor *should* have mentioned them before setting a homework problem where the simple solution uses multiple threads.) – Stephen C Dec 31 '11 at 11:50
  • @StephenC - I agree, the homework is quite inappropriate for the level of Java being taught. At the same time, I doubt permanent harm will be done :) – Perception Dec 31 '11 at 11:56
  • I usually stick with NIO and selectors to avoid the messy synchronization business :-) That's slightly more complicated though. – aioobe Dec 31 '11 at 14:24
  • @Perception - This has nothing to do with my blood pressure, nor my spleen. This is about correct programming and ensuring good habits in newer programmers. Correct Map iteration has been covered multiple times here on Stack Overflow already. http://stackoverflow.com/questions/46898 http://stackoverflow.com/questions/1066589 This isn't just, "what some third party website said." – rfeak Dec 31 '11 at 18:33
1

You can iterate over all the values in the Hashtable and do what you wish to all of them:

Map<String, Connection> users;
for (Connection connection : users.values()) {
    // Send the message to each Socket here.
}
duffymo
  • 305,152
  • 44
  • 369
  • 561
0

Hashtable has keySet() which returns all key entries in that table. I am posting this from mobile, couldnt get you example link. If you want all connection list you can use entrySet().

kosa
  • 65,990
  • 13
  • 130
  • 167