Некоторые проблемы с хешированием. Удаление объектов из хеш-таблицы - PullRequest
0 голосов
/ 23 января 2012

У меня проблемы с удалением клиентов из канала.

Это код, который у меня есть на данный момент:

Serverside:

private Hashtable<String, ArrayList<String>> channels = new Hashtable<String, ArrayList<String>>();

    public synchronized void logMeOut(String username) throws RemoteException {
        for(Client c : clients){
            if(c.findName().equals(username)){
                clients.remove(c);
                disconnectAllChans(username);
                System.out.println(username + " removed from clientlist.");
            }
        }
        updateJListForOnlineUsers(); //Callback for other clients to update the userlist.
    }

  public void disconnectAllChans(String username) throws RemoteException{
    for(Enumeration e = channels.elements(); e.hasMoreElements();){
        if(channels.contains(username)){
            channels.remove(username);
        }
    }
    updateJListForUsersInChannel();
    System.out.println("User " + username + " left all channel");
}

Я пробовал оба типа if (channel.contains (имя пользователя) и containsKey. Кажется, ни один из них не выполняет эту работу. Когда я покидаю сервер, на котором выполняется метод выхода из системы, клиент просто зависает. происходит вечный цикл в этом цикле перечисления.

РЕДАКТИРОВАТЬ: клиент только зависает, если он присоединился к каналу. Если канал для пользователя пуст, он сразу выходит.

Есть идеи, как должен выглядеть код?

**

Решение:

**

Так что да, я понял это, но я бы не стал без вас, ребята. Спасибо

Я только что запустил метод рассоединения внутри метода разъединения всех каналов, который опубликовал brainzzy. Вот результат:

@Override
public void disconnectChannel(String username, String channel) throws RemoteException{
    if(isUserInChannelX(username, channel)){
        channels.get(channel).remove(username);
        String message = "User " + username + " left the channel.";
        notifySelf(username, " You have left the channel " + channel);
        notifyChannelSystem(channel, "SYSTEM", message);
        updateJListForActiveChannels();
        if(channels.get(channel).isEmpty()){
            channels.remove(channel);
        } 
    }
}

public void disconnectAllChans(String username) throws RemoteException{
    for (String channel : channels.keySet()) {
    ArrayList<String> members = channels.get(channel);
        if (members.contains(username)) {
            disconnectChannel(username, channel);
            System.out.println("User " + username + " left channel " + channel);
        }
    }
    updateJListForUsersInChannel();
}

Я чувствую себя немного глупо ^^ Спасибо людям!

Ответы [ 2 ]

5 голосов
/ 23 января 2012

В вашем коде есть бесконечный цикл:

for(Enumeration e = channels.elements(); e.hasMoreElements();){
    if(channels.contains(username)){
        channels.remove(username);
    }
}

Вы никогда не снимаете элемент с перечисления e, поэтому e.hasMoreElements всегда будет возвращать true.Вы, вероятно, хотите что-то более похожее на это:

ArrayList<String> channel = null;
for(Enumeration e = channels.elements(); e.hasMoreElements(); channel = e.nextElement()){
    if(channel.contains(username)){
        channel.remove(username);
    }
}

В качестве примечания, вы столкнетесь с ошибками одновременного изменения с вашим текущим кодом.

2 голосов
/ 23 января 2012

Замените for на цикл foreach, усложнив ошибочные ошибки бесконечного цикла, которые вы допустили, если неправильно обработать перечислитель:

for (String channel : channels.keySet()) {
    ArrayList<String> members = channels.get(channel);
    if (members.contains(username)) {
        members.remove(username);
    }
}

Я думаю, что это будет делать то, что вы хотите.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...