#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
? Конечно, не ajava.util.Date
, потомуdate.toString()
что это определенно не то, с чемLong.parseLong()
можно справиться. Если это ajava.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 . Как это сделать?