一个网易java的面试题

在java中,集合Set中的元素内容可以改变吗?为什么?
网易内推时候问到了这个问题,记得当时网易实习生笔试题也有这个问题,现在还不是很清楚这个问题。  有没有大神解答下??谢谢。。

下面是我的测试代码:我感觉可以改变啊。但是既然问了这个面试题,感觉应该是不可以改变的。而且,set集合中没有get方法。只能通过遍历查找元素吧??
import java.util.*;

class Student {
	int name;

	public int getName() {
		return name;
	}

	public void setName(int name) {
		this.name = name;
	}

	Student(int name) {
		this.name = name;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + name;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Student other = (Student) obj;
		if (name != other.name)
			return false;
		return true;
	}

}

public class TestSet {

	public static void main(String[] args) {
		Student s1 = new Student(12);
		Student s2 = new Student(120);
		HashSet<Student> set = new HashSet<>();
		set.add(s1);
		set.add(s2);
		s1.setName(22222);
		Student s3 = new Student(12);
		set.add(s3);
		System.out.println(set.size());
		Iterator<Student> iterator = set.iterator();
		while (iterator.hasNext()) {
			System.out.println(iterator.next().getName());
		}
	}
}
运行结果如下:
3
120
22222
12

全部评论
在迭代的时候可以改变的吧。 一般来说,改变后,就相当于找不到那个元素了,删也删不掉。 即所谓的内存泄漏了。 不知道分析的对不对。
点赞 回复 分享
发布于 2016-09-17 12:24
不影响那个元素的hash值就可以改变。 影响的话:个人猜测两个影响: 1 可能找不到那个元素了。 java貌似是用引用计数来管理内存,估计不会内存泄漏。 2 [[1,2,3],[1,2]]假设set集合为这个,改变第一个[1,2,3]为[1,2]这样,set集合就有重复元素了。 具体还是看源代码怎么实现的把。
点赞 回复 分享
发布于 2016-09-17 12:37
你调用remove s1不起作用的 内存泄露就是在这里。你重新加个一样的s1会成功的
点赞 回复 分享
发布于 2016-09-17 13:33
删除再重新添加吧。
点赞 回复 分享
发布于 2016-09-17 12:30
set实际还是map,map的key肯定不能改,改了就是另外一个元素了,只是是删除,重新加。
点赞 回复 分享
发布于 2016-09-17 12:34
HashSet底层是使用hashmap实现的,set中的元素存储在map中的key上,key的位置是根据hasCode计算出来的,是唯一的,如果修改了元素值,hasCode值就改变了。
点赞 回复 分享
发布于 2016-09-17 12:38
如果set中放的是不可变类,像Integer这样的,把它放到set中之后就不能再改变了,像你写的测试用例,是一个可变类,把它放到set后,通过引用能改变它的实例变量,那就可以改变,而如果改变的是关键域(跟hash值计算有关的),那么元素的hash值变了,会不会重新计算一次hash值,重置在set中的位置就不清楚了,否则hash值还是一样的,在set中位置不变。
点赞 回复 分享
发布于 2016-09-17 13:20
我个人认为 这个学生类重写了hashcode 而且与name有关 在改变name的时候 hashcode改变了以后会重新计算位置插入 但是基础数据 hashcode基本是固定 改变它值的同时肯定也改变了hashcode 也得重新匹配 轻喷
点赞 回复 分享
发布于 2016-09-17 13:50
顶起来
点赞 回复 分享
发布于 2016-09-17 17:44
个人分析:你的代码出现这样的结果是因为s1的name值被你改了,但是s1在Set内部桶的位置并没有改变,所以你遍历这个Set可以得到最新的值。但是,既然你改了s1的name属性值,因此s1的hashcode变了,如果你想删除这个s1也就删不掉了,这是应该就发生了内存泄露,具体表现就是你remove(s1)之后,这个Set的大小应该还是3。
点赞 回复 分享
发布于 2016-09-17 18:19
Set不行。 从使用者的角度考虑,HashSet底层实现是HashMap,如果改变了一个对象obj的key,hashcode、equals就变了,但是这个对象还在原来的位置上!如果用set.add(obj),这个对象还会再添加到set一次,这与Set的元素唯一性不符合; 但是如果修改结果不影响equals,也就是说oldObj.equals(newObj) == true(即使hashcode变了),那么就是可以修改的。但是此时set中oldObj、newObj同时存在,遍历都可输出; 对于TreeSet,也是一样的考虑,但变成了compare; 总的来说就是,看实际的需求
点赞 回复 分享
发布于 2016-09-17 18:36
你把name!=other.name 换成!name.equals(other.name) 看看size是几? 属性改变后 若不影响hashcode 和 equals方法的返回结果 是可行的
点赞 回复 分享
发布于 2016-09-18 01:01

相关推荐

Noob1024:一笔传三代,人走笔还在
点赞 评论 收藏
分享
头像
11-18 16:08
福州大学 Java
影流之主:干10年不被裁,我就能拿别人一年的钱了,日子有盼头了
点赞 评论 收藏
分享
评论
点赞
11
分享
牛客网
牛客企业服务