【问题标题】:a HashSet.contains() returning an Object一个 HashSet.contains() 返回一个对象
【发布时间】:2015-06-06 20:50:39
【问题描述】:

假设我在 Collections 中使用 A 类型。

class A {
    ThisType thisField; 
    ThatType thatField; 
    String otherField; 
}

只有thisFieldthatField 与识别A 的实例相关——因此它的equals() 和随之而来的hashCode() 方法被相应地覆盖。 这样,在HashSet<A> setOfAs 中,A 的对象在其 (thisField,thatField) 值对中是唯一的。

在应用程序的某处,我需要查找Set 以获取A 的实例,如果存在,则打印其otherField--元信息。

我可以

i.) 在 setOfAs 上获取迭代器,查看每个条目的 thisFieldthatField 值,如果它们都匹配,则打印其 otherField

ii.) 使用自映射HashMap<A,A> selfMapA,其中键和值是每个条目中的相同对象。使用 (thisField,thatField) 值对实例化 A 以查找 selfMapA 并按原样获取其匹配条目,就好像它在那里一样。

(i) 是O(n)-- 尽管它在恒定时间内找到它,但它并没有在恒定时间内得到对象。

(ii) 在恒定时间内获取对象,并且是我们在系统中一直使用的对象。但是,它使用了两倍的内存。

我正在寻找的是一个集合结构,它可以在恒定时间内获取它找到的对象条目。例如,一个带有 contains(Object) 方法返回一个 Object,如果它存在则它找到的对象,而不是像 HashSet.contains() 那样的 boolean

这些有更好的替代品吗?有没有办法解决这个问题?

【问题讨论】:

  • 也许 HashMap.get(Object key) 然后检查它返回的 null 是否是常量,我不确定
  • 对于您所描述的问题,正确答案是已接受的答案,但您的设置有点奇怪。为什么不直接删除字段otherField 并使用HashMap<A, String>
  • @pbabcdefp 也可以。但是在现有系统中需要更改类型

标签: java performance collections hashset asymptotic-complexity


【解决方案1】:

正如 User235... 所说,HashSet 是使用 HashMap 实现的,因此两者之间的内存使用差异可以忽略不计。这具有恒定的时间加法和查找,因此在时间复杂度方面你不能做得更好。所以考虑到这一点,使用 hashmap 可能是最好的答案。

public class Database<A>{
    private HashMap<A,A> db = new HashMap<A,A>();

    /** Adds a to this database. If there was already a in this database,
     * overwrites the old a - updates the metaData 
     */
    public void add(A a){
        db.put(a,a);
    }

    /** Removes a from this database, if present */
    public void remove(A a){
        db.remove(a);
    }

    /** Returns the metadata associated with a in this database.
     * As instances of A hash on thisField and thatField, this
     * may be a different string than a.otherField.
     * Returns null if a is not present in this database.
     */
    public String getMetaData(A a){
        A dat = db.get(a);
        return dat != null ? dat.otherField : null;
    }
}

【讨论】:

    【解决方案2】:

    HashSet 是使用 HashMap 实现的,所有值都设置为虚拟对象,因此选项 2 实际上应该比 HashSet 使用更少的内存。我会选择选项 2。

    【讨论】:

    • 我会调查源代码。现在还不清楚你在说什么。
    • 尚未抬头但已确信。我的 prev.comment 去哪儿了?
    • HashSet 不会比HashMap 占用更多内存,因为虚拟对象是类常量private static final Object PRESENT = new Object();
    • @maaartinus:额外的内存用于 HashSet 对象本身。
    猜你喜欢
    • 2015-06-03
    • 2014-05-27
    • 2014-05-22
    • 2017-03-06
    • 2011-01-25
    • 1970-01-01
    • 1970-01-01
    • 2016-08-30
    • 2010-10-22
    相关资源
    最近更新 更多