Java HashSet与ArrayList
因此,我有一个自定义类,将有一组另一个自定义类的学生。所以它看起来像这样:Java HashSet与ArrayList,java,arraylist,collections,set,hashset,Java,Arraylist,Collections,Set,Hashset,因此,我有一个自定义类,将有一组另一个自定义类的学生。所以它看起来像这样: public class Class { private Set<Student> students; // other methods } 公共类{ 私立学校学生; //其他方法 } 现在,我将在学生集合中添加和删除许多学生,并且我还将更改已经在学生集合中的学生的许多私有字段 问题:我应该使用什么数据结构来最好地实现这一点?由于我将更改set Student中Student对象的属性(
public class Class {
private Set<Student> students;
// other methods
}
公共类{
私立学校学生;
//其他方法
}
现在,我将在学生集合中添加和删除许多学生,并且我还将更改已经在学生集合中的学生的许多私有字段
问题:我应该使用什么数据结构来最好地实现这一点?由于我将更改set Student中Student对象的属性(从而更改hashcodes),是否应改为使用ArrayList?对于散列集合,如
HashSet
,键应为不可变。Hashset在内部使用哈希来决定存储对象的存储桶。在检索对象时,它还将使用哈希来查找对象存储桶。如果在存储后更改对象,则可能会更改对象的哈希代码,并且Set可能无法检索正确的对象。如果在将对象添加到集合后仍需要更改对象,则使用哈希集合不是一个好的选择。选择Arraylist
,但请注意,使用Arraylist
,您将失去快速检索所需学生的优势,就像使用集合一样 当对象的等于
方法的结果将更改时,不应使用集合
。如果您是通过一个稳定的唯一ID号来识别学生,并且等于
只需检查该ID,那么使用集合
就可以了
请注意,HashSet
将使用hashCode
进行索引和比较,并且hashCode
应完全包含用于确定等于的字段。正如你们所说的学生,一定有像id或rollno这样的东西是独一无二的。如果是,则重写hashcode方法,并根据其id实现hashcode。那么更改student的任何其他属性都不会对哈希代码产生影响
选择集合或列表完全取决于您的需求。阅读此链接,它将澄清Set和list之间的区别
如果您在一个集合中使用对象,那么您可以尝试覆盖这两个属性,以便控制唯一性。
注意:如果将可变对象用作集合,则必须非常小心
元素如果
对象的更改方式会影响equals比较,而
对象是集合中的一个元素。这是一种特殊情况
禁止是指不允许集合包含自身
作为一个元素
因此,如果要使用HashSet
如果将hashCode()
和equals()
设置为基于inmutable字段,则不会出现此问题。例如,为每个实例使用唯一的studentID
我应该使用什么数据结构来最好地实现这一点?既然我将在set Student中更改Student对象的属性(从而更改hashcode),我是否应该改用ArrayList
如果set元素的hashcode可能更改,则不应使用HashSet
。(如果这样做,数据结构将中断,集合中的元素可能会丢失。)
但是我怀疑您是否应该使用ArrayList
,因为如果hashcode()
对对象的更改敏感,那么equals(object)
也很可能敏感。这意味着包含(…)
和类似的方法将无法找到对象
我认为你应该使用Map
类型,并使用“学生标识符”作为键
(您也可以重写hashcode
和equals
,这样equality意味着两个对象具有相同的id。但这使得equals(Object)
对于其他用途毫无用处。)根据您的要求,我认为最好的结构应该是Map。Set实际上使用了内部的映射结构,并且您还需要注意equals方法重写以更好地查找。set和arraylist find目标对象需要采取一些查找算法,因此它的效率不如预期(特别是在非常大的收集情况下)。即使map会浪费一些空间,但是如果您的ID是某种原始类型,则可以在.
问题:我应该使用什么数据结构来最好地实现这一点?
因为我将更改集合中学生对象的属性
学生(因此更改哈希代码)我应该使用ArrayList吗
相反
如果要更改hashCode或equals使用的值,则不可能使用HashMap或HashSet
你是说你想删除和添加很多。问题是你是想按顺序做还是随机做(基于索引)。如果按顺序添加、删除,那么最好的选择肯定是LinkedList。如果随机访问对象,则ArrayList的效率要高得多。当涉及到ArrayList
和HashSet
的行为时,它们是完全不同的类
ArrayList
ArrayList
不验证重复项
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
确保没有重复项
- 提供一个
O(1)
contains()
方法,但不保留顺序
add contains next notes
HashSet O(1) O(1) O(h/n) h is the table
- 非线程安全和t
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 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