1

Currently I am writing a chat channel for my game. Players can create chat channels and others can join it. This is what I have so far but i do not know how to return the collection of players. MultiHashMap is deprecated and it told me to use MultiValueMap instead on the commons.apache docs.

private static MultiMap<Channel, Client> channels;

now in my constructor it creates channels

    public Channel(Client owner) {
        this.owner = owner;
        channels = new MultiValueMap<>();
    }

What i'm trying to do is return the collection of players. This does not work...

    public static boolean create(Client player) {
        Channel channel = new Channel(player);
        channels.get(channel).get(player).bla();
        return true;
    }

Help is appreciated. I tried using a MultiKeyMap but the problem with that is that I cannot create Channels unless they take 2 parameters for the key and 1 for the value which is not what I need. If theres a better alternative please let me know.

Mark Peters
  • 80,126
  • 17
  • 159
  • 190
  • 1
    Try breaking up your `.get(channel).get(player).bla()` line into separate lines to help see you're actually doing there. Also of note, is you're assigning a static field from an instance context (i.e. from a constructor). That is almost always a mistake. – Mark Peters Aug 10 '15 at 14:43
  • @MarkPeters Thanks for your comment. the #get(player) doesn't take the player object, it needs a numeric value but the problem with that is that i'd need to check indexes which will make my life harder. – QuestionsDaily Aug 10 '15 at 15:28
  • Why are you calling `bla()` on the `Client` retrieved from the `Channel` instead of on the incoming argument? If you are trying to get the players for the right channel, why not test the argument in each via `channels.get(channel).contains(player)`? You might also consider a different data structure that does not require a dummy channel to be used for lookup and potentially dummy `Client` for lookup. – Paul Bilnoski Aug 10 '15 at 16:33
  • @PaulBilnoski `bla()` is just a test method inside the Client class. I was wanting to retrieve the player and execute that method. It's not possible with `channels.get(channel).get(player)` is there any alternative map that would return my players collection? for example something like `channels.get(channel).getPlayer().bla()` will make my life easier aswell. – QuestionsDaily Aug 10 '15 at 17:38

1 Answers1

0

The MultiMap#get(key) method actually returns a Collection, but you would need to cast it. So you can get all the players for a channel and then iterate over them to perform any operation.

Collection<Client> players = (Collection<Client>)channels.get(channel);
for (Client player : players) {
   player.bla();
}

However, I don't quite understand your data model. The create method,

public static boolean create(Client player) {
    Channel channel = new Channel(player);
    channels.get(channel).get(player).bla();
    return true;
}

creates a new Channel but does not add it to the map. Also the Channel constructor is creating a static MultiMap which is supposed to hold the mapping of channels and players, but a new map would be created with every new Channel.

If what you want to achieve is this

  1. A Channel can have multiple Client Players
  2. A Player can subscribe to multiple Channel

then something like this would help you

public PlayerChannelMap {
    public static final MultiMap<Player, Channel> map = new MultiValueMap<>();
}

public Channel {

    private List<Client> players = new ArrayList<>();

    public addPlayer(Client player) {
        players.add(player);
        PlayerChannelMap.map.put(player, this));
    }

    public List<Client> getPlayers() {
       return players;
    }
}

where you have a single MultiMap<Player, Channel> map for the application. You can get all the player from a channel by channel.getPlayers() and all the channels for a player from the map by (Collection<Channel>)PlayerChannelMap.map.get(player). Note that having the map in a static class is not the ideal solution (a singleton or an in memory cache would be the way to go) and it's just to give an idea of what I am talking about

Dipanjan
  • 26
  • 2
  • That's awesome but a player can only subscribe to ONE channel, if he wants to subscribe to another channel he wil have to leave the current channel, I assume the way to go for that is making the Key Channel and the Value Client? thank you for the answer. Also each Channel exists out of a name which is a String (The user's username), is there a way to return a channel depending on the name? Something like ` channel.getChannelName(player.getUsername())` which returns a collection of Channel? – QuestionsDaily Aug 11 '15 at 13:31
  • Oh also, it tells me `map` is not initialized @ PlayerChannelMap. And I cannot instantiate the MultiMap class. Any ideas? – QuestionsDaily Aug 11 '15 at 14:10
  • Ahhh... right, my bad. I have edited the post now. You would have to initialise the map in the declaration itself. If the player can subscribe to a single channel, then you don't need a MultiMap and a simple Map would suffice. But the key would have to be the player if you want to look up the channel, the player has subscribed to. And if you want to do that through the user name, just create a Map with the player's username as the key. – Dipanjan Aug 12 '15 at 09:58