【问题标题】:Which collection should I use to check if a value is in the collection of 100K elements?我应该使用哪个集合来检查值是否在 100K 元素的集合中?
【发布时间】:2013-05-24 10:30:30
【问题描述】:

我是 Java 新手,不知道 java 集合实现之间的区别。

我必须处理多达 100K 的导入数据记录。该列表中可能有重复项。我必须把所有这些都放到数据库中。在导入之前我清理了数据库表,所以一开始在 DB 中没有重复。

使用休眠模式批量插入数据。 我想做这样的事情:

SomeCollectionClass<Integer> alreadyInsertedRecords;
//...
if (!alreadyInsertedRecords.contains(currentRecord.hashCode()) {
    save_to_database(currentRecord);
    alreadyInsertedRecords.put(currentRecord.hashCode());
} else {
    logger.log("Record no 1234 is a duplicate, skipping");
}

我应该使用哪个集合类来检查记录是否已插入到数据库中?

正如我所说,可能有超过 100 000 条记录,因此集合应该快速搜索、快速插入并且内存占用少。

【问题讨论】:

  • planetjones 说了什么。此外,您应该只使用hashCode(),前提是它保证每个对象都不同。否则,您可能会在contains() 得到一些误报。
  • @Pescis:这是完全错误的。阅读HashSet、equals和hashCode的javadoc。
  • HashSet 比 TreeSet 快吗?
  • @SWilk 测试你就知道了。

标签: java performance collections tree


【解决方案1】:

您可以尝试使用HashSet。请记住,包含对象的类必须正确实现方法 hashCode() 和 equals()。

【讨论】:

    【解决方案2】:

    如果条目是可排序的,您可以使用 TreeSet 集合,只要它们具有有效的 compareTo()equals() 方法,它将自动修剪所有重复的条目。

    这个合集还有provides guaranteed log(n) time cost for the basic operations (add, remove and contains).[reference]

    如果您有权访问hashCode() 功能,则可以使用HashSet。它的工作方式与 TreeSet 类似(插入时修剪欺骗),而且速度更快。

    Colsult Hashset vs Treeset 询问有关这两个系列的详细信息。

    如果可能,请使用HashSet

    【讨论】:

    • 我认为 HashSet 更快,因为它提供了constant time 访问权限。
    • 我只想存储整数标识符,而不是整个对象,它们实际上是使用.hashCode() 方法生成的。看来 TreeSet 是要走的路。
    • 好的,我刚刚重新加载了页面。好像HashSet比较好,Integer有hashCode()方法,所以HashSet才是。
    【解决方案3】:

    如果你不想重复,你可以使用

    Set<Integer> alreadyInsertedRecords = new HashSet<Integer>()
    

    【讨论】:

      【解决方案4】:

      我不会为此使用集合,因为它可以在数据库级别完成。您可以使用 insert where not exists 语句。

      例如

      insert into people (firstName, lastName) 
      select 'Foo', 'Bar'
      where not exists (
          select 1 from people where firstName = 'Foo' and lastName = 'Bar'
      )
      

      【讨论】:

      • 您不认为检查给定对象是否在应用程序内存中重复在性能方面比调用数据库查询更有效吗?
      • 只要列被索引,都是一样的。这只是一个 java 索引查找与数据库索引查找。两者都应该是常数时间 O(1)
      • 其实再想一想你是对的。涉及额外的网络流量。但好处是你不需要在 JVM 的内存中保留 100,000 条记录
      • 是的,这就是我的想法;实际上不仅仅是网络流量,还有设置查询参数,在数据库和客户端进行查询解析,在数据库端将查询添加到重做日志中以及更多成本更低的操作;我的粗略猜测是,在应用程序端检查它的成本至少比在数据库端低 10 倍
      • 你真的不应该那样想。最坏的情况是,对于 n 条记录,您将对数据库进行 n 次插入 [复杂度 = O(n)]。即使您通过检查 JVM 中的集合设法避免了一半的插入 (n/2),它仍然是 O(n) 的复杂度,因为 O(n/2) = O(n)。 en.wikipedia.org/wiki/Time_complexity。因此,我会选择避免将集合存储在内存中的解决方案,因为这两种解决方案的复杂度都是 O(n)。
      猜你喜欢
      • 1970-01-01
      • 2021-12-22
      • 2021-05-05
      • 2010-11-23
      • 1970-01-01
      • 2014-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多