假设我有一个List<Message> conversation
字段的消息Date
列表。
public class Message {
private Date time;
...
}
我希望在一个时间范围内找到所有邮件,由两个Date
个对象fromDate
和toDate
分隔:
public List<Message> getMessagesInRange(final Date fromDate, final Date toDate, final List<Message> conversation) {
List<Message> messagesInRange = new ArrayList<Message>();
...
return messagesInRange;
}
消息列表按时间排序(较旧的消息在较新的消息之前添加)。现在,我可以从头开始遍历整个列表,并填充messagesInRange
添加指定范围内的所有消息。一旦我达到比toDate
更近的日期,我可以结束迭代,因为我知道列表已经排序。
但也许在指定范围内没有消息,从头开始迭代是浪费时间。我想知道一种有效的方法来获取列表中第一个消息的引用,并从那里进行迭代。也许这可以通过二分搜索来完成?
答案 0 :(得分:1)
Java代码:
MessageComparator messageComparator = new MessageComparator();
SortedSet<Message> allMessages = new TreeSet<>(messageComparator);
public List<Message> getMessagesInRange(final Date fromDate, final Date toDate, final List<Message> conversation) {
return new ArrayList<Message>(allMessages.subSet(
messageComparator.minFrom(fromDate), true, messageComparator.maxFrom(toDate), true).values());
}
实施例子:
public class Message {
private static final AtomicLong ID_COUNTER = new AtomicLong();
private final long timestamp;
private final String text;
private final long id;
public Message(Date time, String text) {
this(time, text, ID_COUNTER.incrementAndGet());
}
private Message(Date time, String text, long id) {
this.timestamp = time.getTime(); // (a) Date is mutable & (b) better memory consumption
this.text = text == null ? "" : text;
this.id = id;
}
... // getters & logic (if any)
// Keep in mind - equals & compareTo should be in sync.
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (null == obj) {
return false;
}
if (!obj.getClass().equals(getClass())) {
return false;
}
Message that = (Message) obj;
return timestamp == that.timestamp && id == that.id && message.equals(that.message);
}
}
public class MessageComparator implements Comparator<Message> {
// Keep in mind - equals & compareTo should be in sync.
public int compare(Message m1, Message m2) {
if (m1 == null ? m2 == null : m1.equals(m2)) {
return 0;
}
if (m1 == null) {
return -1;
}
if (m2 == null) {
return 1;
}
int c = Long.compare(m1.timestamp, m2.timestamp);
if (c != 0) {
return c;
}
c = m1.text.compareTo(m2.text);
if (c != 0) {
return c;
}
c = Long.compare(m1.id, m2.id);
return c;
}
public Message minFrom(Date date) {
return new Message(new Date(date.getTime()), null, -1);
}
public Message maxFrom(Date date) {
return new Message(new Date(date.getTime() + 1), null, -1);
}
}