Since you want to get last items by date, thus the key of the Map<Date, Book> books
you can do the following:
protected static List<Book> getLastXBooks(Map<Date, Book> books, int x) {
return books.entrySet().stream()
.sorted(Comparator.<Entry<Date, Book>, Date> comparing(Entry::getKey).reversed())
.limit(x)
.map(Entry::getValue)
.collect(Collectors.toList());
}
protected static List<Book> getBooksOfLastXSeconds(Map<Date, Book> books, int seconds) {
long now = System.currentTimeMillis();
long msAgo = System.currentTimeMillis() - seconds * 1000;
return books.entrySet().stream()
.filter(e -> e.getKey().getTime() <= now && e.getKey().getTime() >= msAgo)
.sorted(Comparator.<Entry<Date, Book>, Date> comparing(Entry::getKey).reversed())
.map(Entry::getValue)
.collect(Collectors.toList());
}
In getBooksOfLastXSeconds
I added the sorting to make the result easy to compare. As of the question it isn't necessary.
Let's have an example:
public static void main(String[] args) {
Map<Date, Book> books = new HashMap<Date, Book>();
for (int i = 0; i < 100; i++) {
Book book = new Book("Book " + (100 - i));
books.put(new Date(System.currentTimeMillis() - i * 100), book);
System.out.println(book);
}
List<Book> last50 = getLastXBooks(books, 50);
System.out.println(last50); // [Book: Book 100, Book: Book 99, ... Book 51, Book: Book 50]
List<Book> booksOfLast2Seconds = getBooksOfLastXSeconds(books, 2);
System.out.println(booksOfLast2Seconds); // [Book: Book 100, Book: Book 99, ... Book 82, Book: Book 81]
}
EDIT
What's the most efficient way I can do that?
The most efficient way would be, to have the books already ordered by insertion date. Then it's not necessary to compare all books (do the sort
above) to get the last 50 books. You could use a LinkedHashMap
to preserve the insertion order. The insertion order has to be the natural order of Date
thus the chronological order.