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

相关推荐

吐泡泡的咸鱼:我也工作了几年了,也陆陆续续面试过不少人,就简历来说,第一眼学历不太够,你只能靠你的实习或者论文或者项目经历,然后你没有论文,没有含金量高的比赛和奖项,只能看实习和项目,实习来说,你写的实习经历完全不清楚你想找什么工作?行研?数据分析?且写的太少了,再看项目,这些项目先不说上过大学读过研究生的都知道很水,然后对你想找的岗位有什么帮助呢?项目和实习也完全不匹配啊,你好像在努力将你所有的经历都放在简历里想表现你的优秀,但是对于你想找的岗位来说,有什么用呢?最后只能获得岗位不匹配的评价。所以你需要明白你想要找的岗位要求是什么,是做什么的,比如产品经理,然后再看你的经历里有什么匹配的上这个岗位,或者对这个岗位以及这个岗位所在的公司有价值,再写到你的简历上
点赞 评论 收藏
分享
ResourceUtilization:差不多但是估计不够准确,一面没考虑到增长人口,另一方面也没考虑到能上大学的人数比例,不过我猜肯定只多不少
点赞 评论 收藏
分享
评论
点赞
11
分享

创作者周榜

更多
牛客网
牛客企业服务