【问题标题】:Adavantages of HashSet over ArrayList and vice versaHashSet 优于 ArrayList 的优点,反之亦然
【发布时间】:2015-07-12 05:57:54
【问题描述】:

我对 Java 中的数据结构有疑问。在解决 Java 中的一个典型散列问题时,我使用了 HashSet 数据结构,在出现重复对象(对象内容)之前它工作得很好。由于 HashSet 不支持重复插入,我的逻辑失败了。

我用典型的Arraylist替换了hashset,因为hashset的方法如.add().contains() , .remove() 两者都支持,然后我的逻辑就完美了。

但这是否一定意味着当涉及重复时,ArrayList 是 Hashset 的逻辑选择? Hashset 应该比 ArrayList 有一些时间复杂度优势,对吧?有人可以给我一些关于这方面的见解吗?

编辑:当您想要在涉及重复时进行散列时,理想的数据结构是什么。我的意思是什么时候不应该忽略重复项,应该插入。

【问题讨论】:

  • “做哈希”是什么意思?
  • 将诸如字符串之类的对象添加到基于哈希的数据结构中,并稍后检查它们的存在。如果相同的字符串出现两次,则应重新插入。

标签: java arraylist hashset


【解决方案1】:

如果您特别需要处理重复的HashSetHashMap 将能够完成这项工作。如果您只需要计算添加的对象数量(使用快速查找/等),HashMap<T,Integer> 将是理想的,其中T 是您的对象的类型。如果您确实需要保留对已添加的重复对象的引用,请使用HashMap<T, List<T>>。这样,您可以使用 HashMap 的.containsKey(T t) 进行查找,并遍历结果列表中所有类似的散列对象。例如,您可以创建此类:

public class HashSetWithDuplicates<T> {

    private HashMap<T, List<T>> entries;
    private int size;

    public HashSetWithDuplicates(){
        entries = new HashMap<>();
        size = 0;
    }

    public HashSetWithDuplicates(Collection<? extends T> col){
        this();
        for(T t : col){
            add(t);
        }
    }

    public boolean contains(T t){
        return entries.containsKey(t);
    }

    public List<T> get(T t){
        return entries.get(t);
    }

    public void add(T t){
        if (!contains(t)) entries.put(t, new ArrayList<>());

        entries.get(t).add(t);
        size++;
    }

    public void remove(T t){
        if (!contains(t)) return;
        entries.get(t).remove(t);
        if(entries.get(t).isEmpty()) entries.remove(t);
        size--;
    }

    public int size(){
        return size;
    }

    public boolean isEmpty(){
        return size() == 0;
    }
}

根据您的需要添加功能。

【讨论】:

  • 不明白为什么有人不加评论就否决了这个答案。这似乎正是 SoulRayder 所需要的。重复的对象几乎没有任何意义,除了线程(即使我有疑问)或其他东西。
【解决方案2】:
  • 当您使用 HashMap 时,它会将原始值替换为新的副本。
  • 当您使用 HashSet 时,后续的重复项将被忽略(不插入)。
  • 当您使用 ArrayList 时,它只是将重复项添加到列表的末尾

这一切都取决于您的需求。

【讨论】:

  • 但是在哈希要求方面,Hashset 比 arraylist 有一些时间复杂度优势,对吧?否则,当您可以使用 arraylist 实现相同功能时,为什么还需要 hashset?
  • 为简单起见...如果您需要确保不允许重复,为什么要使用 ArrayList?
  • 查看我的编辑。我希望插入重复项,不应忽略。
  • 通过散列,我猜您希望能够通过其散列值来识别对象?无论如何,我怀疑你想要的是 ArrayList
【解决方案3】:

不清楚您所说的“哈希问题”是什么意思,但也许您正在寻找multiset。来自 Guava 文档:

支持顺序无关相等性的集合,如 Set,但可能有重复元素。多重集有时也称为包。

多重集合中彼此相等的元素被称为相同单个元素的出现。一个元素在多重集中出现的总次数称为该元素的计数(术语“频率”和“多重性”是等价的,但在此 API 中不使用)。

JDK 中不存在这样的东西。

【讨论】:

    【解决方案4】:

    ArrayList 如果您不想重复,则不是合乎逻辑的选择。针对不同用例的不同工具。

    您可以在重复没有意义的区域使用Set,例如一组学生。 List 允许重复。

    【讨论】:

    • 那么当涉及到重复项时想要进行散列时,理想的数据结构是什么?
    • @SoulRayder 你为什么想要这样的东西?列表不使用存储桶来存储数据,这是没有意义的。你想做什么?如果您担心ArrayList 的访问时间,get(int) 是常数时间,如文档中所述
    • 但是 .contains() 是 ArrayList 中的线性时间,对吧?或者在这两种情况下也是这个常数?
    • @SoulRayder 从Set 访问一个项目是线性时间,看看你必须如何迭代它以访问其中的值。如果你展示了你想要做什么,我可以编辑我的答案以更好地适应
    猜你喜欢
    • 2011-08-23
    • 1970-01-01
    • 2012-05-23
    • 2014-05-12
    • 1970-01-01
    • 2015-06-22
    • 2014-04-16
    • 2011-11-21
    • 1970-01-01
    相关资源
    最近更新 更多