Получение последних/новейших записей HashMap

У меня есть HashMap<String, String>, и я ввожу запись в HashMap, например, каждый раз, когда игрок говорит. Bob492 говорит «Привет». и я буду вводить «Bob492» и «Привет» в качестве его значения.

Теперь мне нужен способ захватить последние 5 сообщений в свою собственную строку, по одной строке для каждого.

Как бы я это сделал?

EDIT: Благодаря ответу кажется, что HashMap - не лучший способ сделать это, но очередь может быть лучше. Как бы я этого добился, например.

Это диалог. Боб: Эй, Бобби: О, ты где! Бобби: Я искал тебя. Джозеф: Да, я знаю, я знаю. Джеймс: Я не с тобой разговаривал! Джозеф: Какая разница?!?

И все это будет поставлено в очередь, и я смогу легко как-то получить их имя пользователя и сообщение (я не знаю). Можно увидеть только 5 из этих 6 сообщений, поэтому сообщение Боба исчезнет.

EDIT2: я хочу, чтобы это было похоже на это: A minecraft server


person Lewes    schedule 01.08.2013    source источник
comment
Рассматривали ли вы возможность иметь несколько структур данных (например, хэш-карту и очередь FIFO)?   -  person Basile Starynkevitch    schedule 01.08.2013
comment
Я в замешательстве, что вы имеете в виду, поскольку я никогда не слышал об очереди fifo.   -  person Lewes    schedule 01.08.2013
comment
ключ всегда может содержать одно значение, которое обновляется последним. или вы пытаетесь добиться здесь функциональности очереди?   -  person Anish Mohile    schedule 01.08.2013
comment
Ах, кажется, я пытаюсь создать очередь.   -  person Lewes    schedule 01.08.2013


Ответы (5)


У вас может быть Map из CircularFifoBuffer коллекций Apache.

//maps username to last 5 messages
Map<String,CircularFifoBuffer> map = new HashMap<String,CircularFifoBuffer>();

//putting the values

if(map.get(username) == null){
    CircularFifoBuffer last5messages = new CircularFifoBuffer(5);
    last5messages.add(message);
    map.put(last5messages);
}else{
    //similar code
}

Что такое CircularFifoBuffer?

CircularFifoBuffer — это буфер типа «первым поступил — первым обслужен» с фиксированным размером, который заменяет самый старый элемент, если он заполнен.

Так что автоматически сохраняются последние 5 сообщений, удаляя самое старое сообщение из буфера.

ИЗМЕНИТЬ:

Насколько я понимаю из комментария:

Позвольте мне показать вам, что я имею в виду Боб: Привет, Боб: Мне скучно :l Джозеф: О, привет Джозефари: Привет, Джозеф и Боб Джозеф: О, как вы двое?

class MessageEntry{
    String userName;
    String message;

    public MessageEntry(String userName, String message){
       //store
    }

    public String getUsername(){
        return userName;
    }

    public String getMessage(){
        return message;
    }

}

//just a buffer to store last 5 messages received
CircularFifoBuffer last5messages = new CircularFifoBuffer(5);


//for storing last 5 messages
last5messages.add(new MessageEntry(userName,message));


//for retrieving elements:
Object[] messages = last5Messages.toArray();
//gives you messages that you can use any way you want


for(Object message : messages){
   MessageEntry entry = (MessageEntry)message;

   String userName = entry.getUsername();
   String message = entry.getMessage();

}
person Narendra Pathai    schedule 01.08.2013
comment
Тогда как мне получить сообщение, например второе сообщение? - person Lewes; 01.08.2013
comment
2-е сообщение какого пользователя? - person Narendra Pathai; 01.08.2013
comment
Позвольте мне показать вам, что я имею в виду Боб: Привет, Боб: Мне скучно :l Джозеф: О, привет Джозефари: Привет, Джозеф и Боб Джозеф: О, как вы двое? - person Lewes; 01.08.2013
comment
Проверьте обновленный ответ. Я думаю, вам просто нужно сохранить последние 5 сообщений, которые были получены, а не последние 5 сообщений для каждого пользователя. Поэтому я отредактировал, чтобы добавить и этот код. - person Narendra Pathai; 01.08.2013
comment
Можно ли как-то хранить имена игроков и их сообщения, но не вместе, так как мне нужно впоследствии настроить сообщения. - person Lewes; 01.08.2013
comment
Я отредактировал код, чтобы добавить класс MessageEntry. Проверьте это. - person Narendra Pathai; 01.08.2013
comment
Как мне получить имя пользователя и сообщение? - person Lewes; 01.08.2013
comment
Отредактировали, чтобы добавить и эту часть! Но на самом деле вы должны попробовать что-то сами. Вам просто нужно было зациклить сообщения и бросить, чтобы получить имя пользователя и пароль. В любом случае, вы идете. - person Narendra Pathai; 01.08.2013

К сожалению, HashMap НЕ сохраняет порядок добавления данных. В вашем конкретном случае вы должны использовать LinkedHashMap, потому что этот тип карты точно такой же, как HashMap, но сохраняет порядок, и вы можете перебирать его, чтобы получить последние записи. Но имейте в виду, что у вас не может быть нескольких значений для одного ключа, поэтому я не думаю, что вы ищете карту, а Queue

person mvlupan    schedule 01.08.2013

Есть ли причина, по которой вы используете для этого HashMap? Поскольку HashMap удалит последнюю сыгранную строку, когда игрок снова говорит. Мне кажется, что вам нужна другая структура данных для хранения ваших данных, например очередь fifo.

person Filip    schedule 01.08.2013

HashMap не поддерживает такое поведение. Что вам нужно сделать, так это создать или найти класс, который будет выполнять логическую часть вашего кода. Логика говорит, что вам нужно хранить в каком-то месте пять сообщений. Как простой MessageBuffer, должен сделать эту работу за вас.

class MessagesBuffer {

 private String[] recent;

 public MessagesBuffer(int size) { 
   this.recent = new String[size];
 }

 public void addMessage(String messsage) {

   for(int i = 1; i < recent.lenght; i++) {
     recent[i] = recent[i-1];
   }

   this.recent[0] = message;

 }

/*Other implementation details*/

} 

Когда у вас есть структура, реализующая логику, вы можете использовать Map, чтобы связать ее с человеком.

Map<User,MessageBuffer> recent = new HashMap<>();
person Damian Leszczyński - Vash    schedule 01.08.2013
comment
Но тогда мне потребуется имя игрока для получения данных, которых я не знаю. Мне просто нужен способ сохранить имя игрока и его сообщение. И отправляю игроку обратно максимум 5 новейших сообщений. - person Lewes; 01.08.2013
comment
Тогда не используйте карту, а составьте сообщение в форме User + ":" message и поместите его в буфер. - person Damian Leszczyński - Vash; 01.08.2013

Вы можете использовать LinkedHashMap, это

    LinkedHashMap m = new LinkedHashMap(16, 0.75f, true) {
        protected boolean removeEldestEntry(java.util.Map.Entry eldest) {
            return size() > 5;
        };
    };

удостоверяется, что карта содержит 5 самых последних записей

    m.put("1", "1");
    m.put("2", "2");
    m.put("3", "3");
    m.put("4", "4");
    m.put("5", "5");
    m.put("6", "6");
    System.out.println(m);

выход

{2=2, 3=3, 4=4, 5=5, 6=6}

person Evgeniy Dorofeev    schedule 01.08.2013