Как изменить значение stream?

#java #java-stream

#java #java-stream

Вопрос:

Я создаю приложение для общения в чате.

Я использую память для реализации repository .

В read методе я хочу изменить isReadOrNot true и вернуть измененные сообщения, где значение isReadOrNot равно false , а отправитель и получатель совпадают.

store является объектом HashMap.

 Map<Long, Message> store = new HashMap<>();
 

Я покажу вам Message класс и как я пробовал, которые потерпели неудачу.

 public class Message {
    private long index;
    private long sender_id;
    private long receiver_id;
    private Date transmitted_time;
    private Date read_time;
    private boolean readOrNot;
    private String text;
    .
    .
    .
}
 

как я пытался:

 public List<Message> read(long sender_id, long receiver_id, Date date) {
        long count = store.values()
            .stream()
            .filter(
                    message -> !message.isReadOrNot()
                            amp;amp; message.getSender_id() == sender_id
                            amp;amp; message.getReceiver_id() == receiver_id
                            amp;amp; Long.parseLong(message.getTransmitted_time().toString()) > Long.parseLong(date.toString())
            ).count();

        return null;
    }
 

Вопрос в том, как изменить receivedOrNot значение до date и совпадает с sender_id , receiver_id .

Комментарии:

1. Почему вы его используете count , должно быть map в вашей проблеме!

2. Я пытался использовать для предложения, но потерпел неудачу.

3. Несвязанный: что такое Date ? Конечно, не a java.util.Date , потому date.toString() что это определенно не то, с чем Long.parseLong() можно справиться. Если это a java.util.Date , то date.getTime() вернет желаемое long значение, хотя вы могли бы просто использовать compareTo() так: message.getTransmitted_time().compareTo(date) > 0 , что является кратчайшим способом его записи и четко показывает цель выражения.

4. Я использую java.sql.date, а не java.util.Date

5. java.sql.Date является подклассом java.util.Date , и date.toString() все еще не является чем-то таким длинным, с чем могла бы справиться функция parseLong(). Мой комментарий в равной степени подходит для java.sql.Date .

Ответ №1:

Потоки не всегда лучший подход. Если бы я делал это, я бы просто повторял сообщения, используя цикл, а затем message соответствующим образом модифицировал объект.

 public List<Message> read(long sender_id, long receiver_id, Date date) {
     List<Message> results = new ArrayList<>();
     for (Message message : store.values()) {
        // filter here
        if (!message.isReadOrNot()
                         amp;amp; message.getSender_id() == sender_id
                         amp;amp; message.getReceiver_id() == receiver_id
                         ...
                         ...
             ) {
                results.add(message);
                message.setReadOrNot(true);
                // other changes to message here
                ...
                ...
        }
     }
     return results;
}
 

Комментарии:

1. Каковы плюсы использования вашего ответа, а не предыдущего ответа?

2.В предыдущем ответе нет ничего плохого. Это просто вопрос личных предпочтений. Однако постановка задачи относительно проста, поэтому использование потоков не дает никаких реальных разъяснений. И в этом случае простой цикл более эффективен (в streams API есть значительные накладные расходы). Но в первую очередь для меня, согласно Java API для peek «Этот метод существует в основном для поддержки отладки, когда вы хотите видеть элементы по мере их прохождения мимо определенной точки в конвейере». И хотя некоторые игнорируют этот совет, я склонен ему следовать.

3. Спасибо за объяснение. Я буду искать более подробную информацию о том, какие значительные накладные расходы. И я уважаю вашу тенденцию.

Ответ №2:

Если я правильно понял, все Message объекты, которые проходят критерии фильтрации, должны быть обновлены setReadOrNot(true) и должны быть возвращены в List .

Если это так, то вы можете использовать peek() и collect(toList()) :

 public List<Message> read(long sender_id, long receiver_id, Date date) {
    return store.values()
        .stream()
        .filter(message -> !message.isReadOrNot()
                         amp;amp; message.getSender_id() == sender_id
                         amp;amp; message.getReceiver_id() == receiver_id
                         amp;amp; message.getTransmitted_time().compareTo(date) > 0)
        .peek(message -> message.setReadOrNot(true))
        .collect(Collectors.toList());
}
 

Чтобы также установить read_time , используйте блок лямбда-выражения:

         .peek(message -> {
            message.setReadOrNot(true);
            message.setRead_time(new Date(System.currentTimeMillis()));
        })
 

Комментарии:

1. Спасибо, что ответили на этот вопрос. Ваше понимание верно.

2. Могу я задать еще один вопрос? Я хочу установить не только readOrNot, но и read_time . Как это сделать?