HashSet与ArrayList

所以我有一个自定义类Class,它将拥有一组另一个自定义类Student。 所以它看起来像这样:

public class Class { private Set students; // other methods } 

现在,我将向学生们添加和删除许多学生,我也将改变已经在学生集中的学生的许多私人领域。

问题:我应该使用什么数据结构来实现这一目标? 由于我将更改set student中的Student对象的属性(从而更改哈希码),我应该使用ArrayList吗?

我应该使用什么数据结构来实现这一目标? 由于我将更改set student中的Student对象的属性(从而更改哈希码),我应该使用ArrayList吗?

如果set元素的哈希码容易改变,那么你不应该使用HashSet 。 (如果这样做,数据结构将会中断,并且集合中的元素可能会丢失。)

但我怀疑你是否应该使用ArrayList ,因为如果hashcode()对对象的更改敏感,那么equals(Object)很可能也是如此。 这意味着contains(...)和类似的方法将无法找到对象。

我认为你应该使用Map类型,并使用“学生标识符”作为关键。

(你也可以覆盖hashcodeequals这样相等意味着两个对象具有相同的id。但这使得equals(Object)无法用于其他目的。)

当它涉及ArrayListHashSet的行为时,它们是完全不同的类。

数组列表

  • ArrayList不validation重复项。
  • get()O(1)
  • contains()O(n)但您可以完全控制条目的顺序。

      get add contains next remove(0) iterator.remove ArrayList O(1) O(1) O(n) O(1) O(1) O(1) 
  • 不是线程安全的并且为了使线程安全,你必须使用Collections.synchronizedList(...)

HashSet的

  • HashSet确保没有重复项。
  • 给你一个O(1) contains()方法,但不保留顺序。

      add contains next notes HashSet O(1) O(1) O(h/n) h is the table 
  • 不是线程安全的并且为了使线程安全,你必须使用Collections.synchronizedSet(...)

这取决于。 当你在谈论学生时,必须有像id或rollno这样独特的东西。 如果是,则覆盖哈希码方法并根据其ID实现哈希码。 然后通过更改学生的任何其他属性对哈希码没有影响。

选择Set或List完全取决于您的要求。 阅读此链接,它将阐明Set和list之间的区别
Set和List有什么区别?

如果您正在使用Set中的对象,那么您可以尝试覆盖hashcode和equals方法,以便控制唯一性在您手中。

当对象的equals方法的结果发生变化时,不应使用Set 。 如果您通过稳定的唯一ID号识别学生,并且equals只检查该ID,那么使用Set就可以了。

请注意, HashSet将使用hashCode进行索引和比较,而hashCode应该恰好包含用于确定equals字段。

对于散列集合(如HashSet ,密钥应该是immutable 。 Hashset在内部使用散列来决定存储对象的存储桶。 而且在检索对象时,它将使用哈希来查找对象桶。 如果在存储后更改对象,则可能会更改对象的哈希码,而Set可能无法检索正确的对象。 如果您需要在将对象添加到集合后更改对象,则使用散列集合不是一个好的选择。 而是选择Arraylist ,但请注意,使用ArrayList您将失去快速检索所需学生的优势,就像使用Set一样。

Set的javadoc说

注意:如果将可变对象用作set元素,则必须非常小心。 如果在对象是集合中的元素的同时以影响等于比较的方式更改对象的值,则不指定集合的​​行为。 这种禁令的一个特例是,不允许将一个集合作为一个元素包含在内。

因此,如果您要使用HashSet如果您使用inmutable字段生成hashCode()equals() ,那么您将不会遇到此问题。 例如,为每个实例使用唯一的studentID。

根据您的要求,我认为最好的结构应该是Map。 设置实际底层使用内部的Map结构,您还需要注意equals方法覆盖以获得更好的查找。 并且set和arraylist发现目标对象需要采用一些查找算法,因此它不如预期的那么高效(特别是在非常大的收集情况下)。 即使map会浪费一些空间,但如果你的ID是某种原始类型,你可以考虑Trove库中原始类型的map实现。

问题:我应该使用什么数据结构来实现这一目标? 由于我将更改set student中的Student对象的属性(从而更改哈希码),我应该使用ArrayList吗?

当然,如果您要更改hashCode或equals使用的值,则无法使用HashMap或HashSet。

您说要删除并添加很多内容。 问题是你是想要顺序地还是随机地(基于索引)。 如果你添加,顺序删除,那么肯定最好的选择是LinkedList。 如果随机访问对象,则ArrayList效率更高。

如果您的代码中有重复数据,那么您应该使用ArrayList,否则您可以使用hashset,如下所示。因此,如果您的代码不需要重复值,则使用Set而不是list,因为该集合将提供更好的性能(O( n)对于列表的O(n ^ 2),这是正常的,因为避免重复是集合的目的。

数组列表

public static void main(String [] args){

 ArrayList arr =new ArrayList(); arr.add("Hello"); arr.add("is"); arr.add("Hello"); System.out.println(arr); //As we are using Arraylist therefore //the duplicate elements are allowed therefore //"Hello" is not removed in the output 

}

HashSet的

public static void main(String [] args){

 HashSet arr =new HashSet(); arr.add("Hello"); arr.add("is"); arr.add("Hello"); System.out.println(arr); //As we are using Hashset therefore //the duplicate elements removed therefore //"Hello" is removed in the output 

}