Java 从项目映射中检索最后n个项目

Java 从项目映射中检索最后n个项目,java,dictionary,data-structures,Java,Dictionary,Data Structures,我有一个map,我想检索插入map的最后50个项目,或者在最后2秒内添加到map的项目(以较大者为准) 我能做的最有效的方法是什么 Map<Date, Book> books = new HashMap<Date, Book>(); Map books=newhashmap(); 注: -我希望最大化吞吐量并最小化延迟。 -我希望在JVM上运行并最小化堆占用。使用堆栈存储日期,然后从堆栈中弹出项作为键。 只要在HashMap中输入内容时按Date作为键,就可以用一句话

我有一个
map
,我想检索插入
map
的最后50个项目,或者在最后2秒内添加到
map
的项目(以较大者为准)

我能做的最有效的方法是什么

Map<Date, Book> books = new HashMap<Date, Book>();
Map books=newhashmap();
注:
-我希望最大化吞吐量并最小化延迟。
-我希望在JVM上运行并最小化堆占用。

使用堆栈存储
日期,然后从堆栈中弹出项作为键。

只要在HashMap

中输入内容时按
Date
作为键,就可以用一句话回答您的问题:

默认情况下,地图没有最后一个条目,它不是合同的一部分。(散列)映射存储内存优化的项

可能的解决办法 已排序的地图:

您可以通过lastEntry方法访问最后一个条目:

NavigableMap<String,Integer> map = new TreeMap<String, Integer>();
// add some entries
Entry<String, Integer> lastEntry = map.lastEntry();
NavigableMap=newtreemap();
//添加一些条目
Entry lastEntry=map.lastEntry();
或者使用链接地图:

Map<String,String> map = new LinkedHashMap<String, Integer>();
// add some entries
List<Entry<String,Integer>> entryList =
    new ArrayList<Map.Entry<String, Integer>>(map.entrySet());
Entry<String, Integer> lastEntry =
    entryList.get(entryList.size()-1);
Map Map=newlinkedhashmap();
//添加一些条目
列表条目列表=
新的ArrayList(map.entrySet());
最后一项=
get(entryList.size()-1);
两者都是本机Java库。

因为您想要获取,因此
地图册的键可以执行以下操作:

  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());
  }
编辑
我能做的最有效的方法是什么?

最有效的方法是,在插入日期之前订购图书。这样就没有必要比较所有的书(进行上面的
排序
)来得到最后50本书。您可以使用
LinkedHashMap
来保留插入顺序。插入顺序必须是日期,因此是时间顺序。

您可以使用树映射或类似的数据结构来保持顺序。如果您正在构建应用程序,我建议将所有数据存储到数据库中,并运行查询以按日期或最后50项提取数据。@ZenWright我不允许使用外部数据库..TreeMap按排序顺序维护顺序,但我希望维护最后的插入顺序..您必须只使用hashmap,否则您也可以使用其他数据结构?我想最大化吞吐量并最小化延迟。我想在JVM上运行并最小化堆占用。我想最大化吞吐量并最小化延迟。我想在JVM上运行并最小化堆占用。@KshitijRoshan推送和弹出操作在堆栈中非常有效,所以我想在这种情况下应该使用堆栈。
Stack
不推荐使用(很久以前)使用
ArrayDeque
instead@FedericoPeraltaSchaffner
LinkedList
也可以使用。@suvojit_007同意。它也可以使用,这是一个偏好问题。我认为
ArrayDeque
在大多数情况下更好,但在这种特殊情况下,
LinkedList
可以完成这项工作。
TreeMap.lastEntry()
给出具有最大/最小键值的条目。向后迭代
LinkedHashMap
应该可以做到这一点。
  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]
  }