Java集合HashSet的hashcode方法引起的内存泄漏问题
注:试了试,arrayList也会有这种问题的。也是使用hashcode来比较的。
import java.util.HashSet;
import java.util.Set;
/**
* Created on 2010-6-7
* <p>Description: [HashSet的hashcode方法引起的内存泄漏]</p>
* @author shixing_11@sina.com
* @version 1.0
*/
public class HashSetTest
{
public static void main(String[] args)
{
Set<Person> set = new HashSet<Person>();
Person p1 = new Person("唐僧","pwd1",25);
Person p2 = new Person("孙悟空","pwd2",26);
Person p3 = new Person("猪八戒","pwd3",27);
set.add(p1);
set.add(p2);
set.add(p3);
System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:3 个元素!
p3.setAge(2); //修改p3的年龄,此时p3元素对应的hashcode值发生改变
set.remove(p3); //此时remove不掉,造成内存泄漏
set.add(p3); //重新添加,居然添加成功
System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:4 个元素!
for (Person person : set)
{
System.out.println(person);
}
}
}
package apistudy;
import java.util.HashSet;
import java.util.Set;
/**
* Created on 2010-6-7
* <p>Description: [HashSet的hashcode方法引起的内存泄漏]</p>
* @author shixing_11@sina.com
* @version 1.0
*/
public class HashSetTest
{
public static void main(String[] args)
{
Set<Person> set = new HashSet<Person>();
Person p1 = new Person("唐僧","pwd1",25);
Person p2 = new Person("孙悟空","pwd2",26);
Person p3 = new Person("猪八戒","pwd3",27);
set.add(p1);
set.add(p2);
set.add(p3);
System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:3 个元素!
p3.setAge(2); //修改p3的年龄,此时p3元素对应的hashcode值发生改变
set.remove(p3); //此时remove不掉,造成内存泄漏
set.add(p3); //重新添加,居然添加成功
System.out.println("总共有:"+set.size()+" 个元素!"); //结果:总共有:4 个元素!
for (Person person : set)
{
System.out.println(person);
}
}
}
运行结果:
总共有:3 个元素!
总共有:4 个元素!
猪八戒-->pwd3-->2
孙悟空-->pwd2-->26
唐僧-->pwd1-->25
猪八戒-->pwd3-->2
总结:
HashSet中,在对应元素添加进set集合后,不要再去修改元素的值,否则对应元素的hashcode值发生变化,此时如果调用
集合的remove(),contains()方法,将不会得到正确的结果。remove()方法并不能正确remove掉对应的元素,造成内存泄漏。
Person.java
view plaincopy to clipboardprint?
package apistudy;
public class Person
{
private String username;
private String password;
private int age;
public Person(String username, String password, int age)
{
this.username = username;
this.password = password;
this.age = age;
}
public String getUsername()
{
return username;
}
public void setUsername(String username)
{
this.username = username;
}
public String getPassword()
{
return password;
}
public void setPassword(String password)
{
this.password = password;
}
public int getAge()
{
return age;
}
public void setAge(int age)
{
this.age = age;
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result + ((password == null) ? 0 : password.hashCode());
result = prime * result + ((username == null) ? 0 : username.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Person other = (Person) obj;
if (age != other.age)
return false;
if (password == null)
{
if (other.password != null)
return false;
}
else if (!password.equals(other.password))
return false;
if (username == null)
{
if (other.username != null)
return false;
}
else if (!username.equals(other.username))
return false;
return true;
}
@Override
public String toString()
{
return this.username+"-->"+this.password+"-->"+this.age;
}
}
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/shixing_11/archive/2010/06/07/5652935.aspx
分享到:
相关推荐
内存管理和优化是编程中至关重要的环节,尤其是在Java这样的高级语言中,由于自动内存管理机制的存在,内存泄漏和溢出问题可能会变得难以察觉但后果严重。本文将深入探讨内存泄漏及其可能导致的内存溢出问题,以及...
1. **静态集合类引起内存泄露** - **示例代码**: ```java static Vector v = new Vector(10); for (int i = 1; i ; i++) { Object o = new Object(); v.add(o); o = null; } ``` 在上述代码中,虽然局部...
4. **重构代码逻辑**:针对特定场景,比如`HashSet`中的对象属性更改导致的内存泄漏,可以通过重写`hashCode()`和`equals()`方法确保即使对象属性更改也能正确识别和删除。 5. **使用工具检测内存泄漏**:利用JVM...
HashSet基于哈希表,无序且唯一,通过hashCode和equals方法保证元素唯一性。TreeSet内部实现为红黑树,元素自动排序,而LinkedHashSet则保持插入顺序。 3. Map接口:Map用于存储键值对,HashMap、HashTable、...
使用这种方式可以方便地在对象间导航,但需注意内存泄漏和循环引用的问题。 2. **对象的一对多关系**: 在Java中,一对多关系是最常见的关联,比如一个班级有多个学生。这通常通过在“多”端的类中定义集合类型的...
在IT行业中,内存泄露是一个非常重要的问题,尤其是在Java这样的编程语言中。标题“黑马程序员------hash改变造成的内存泄露”提示我们,这个问题与哈希值的变化有关,这可能会导致程序无法正确地释放不再使用的内存...
8. **内存泄漏问题**:在`HashSet`中,对象的`hashCode`用于定位存储位置。如果对象的字段被修改,导致`hashCode`改变,那么在尝试删除对象时,由于新的`hashCode`找不到原有的位置,可能导致删除失败,从而引发内存...
54. **Java集合框架结构**:包括接口如List, Set, Map,以及实现类如ArrayList, LinkedList, HashMap等,提供了丰富的数据结构和操作方法。 以上是对Java面试中可能出现的一些关键问题的详细解答,希望能帮助求职者...
Java 内存泄漏简介 - **内存泄漏原因**:探讨导致内存泄漏的常见原因,如循环引用和静态变量。 - **检测工具**:介绍用于检测内存泄漏的工具和技术。 - **预防措施**:提供防止内存泄漏的最佳实践建议。 #### 12. ...
9. **集合框架的选择**:Java集合框架包括List、Set、Queue等接口,以及ArrayList、LinkedList、HashSet、HashMap等实现。根据需求选择合适的集合类型,如需保持顺序,使用ArrayList;需去重,使用HashSet。 10. **...
- **必要性**:避免内存泄漏和内存溢出等问题,提高程序运行效率。 #### 16. 短整型变量的运算问题 - **`short s1 = 1; s1 += 1;`**:使用复合赋值运算符时,Java 会自动进行类型转换,确保结果正确。 - **`short ...
10. **Java集合框架有哪些主要组件?** 集合框架包括List(如ArrayList和LinkedList)、Set(如HashSet和TreeSet)和Map(如HashMap和TreeMap)。它们提供了存储和操作对象的接口和实现。 11. **什么是Java反射API...
其次,深入理解Java集合框架是必备技能。集合框架包括List、Set、Map接口及其实现类,如ArrayList、LinkedList、HashSet、HashMap等。你需要熟悉它们的特性和应用场景,以及如何根据需求选择合适的数据结构。此外,...
1. **List**: List是Java集合框架中的接口,它代表有序的元素序列,支持索引访问。ArrayList和LinkedList是两种常见的实现,前者在随机访问时性能更好,后者在插入和删除操作上更高效。 2. **Set**: Set接口不包含...
Java集合框架包括List、Set和Map接口,以及它们的实现类如ArrayList、LinkedList、HashSet、HashMap等。这些集合提供了丰富的操作方法,方便存储和管理对象。 9. **泛型** 泛型是Java 5引入的特性,允许在类、...
理解Java内存模型,合理设置堆大小,避免创建过大的对象,及时清理不再使用的对象,使用WeakReference和SoftReference管理对象,可以帮助防止内存溢出。 以上仅是部分常见的Java Bug模式,实际开发中还会有更多复杂...
Java Bug模式详解是一种深入理解和解决Java编程中常见错误和陷阱的方法。这些模式通常源于语言特性、API使用不当或对编程规范的误解。本篇将详细探讨一些常见的Java Bug模式,并提供预防和修复策略。 1. **空指针...
6. **垃圾回收**:虽然JVM的垃圾回收机制在源码中并不直接可见,但通过研究`java.lang.ref`和`java.lang.instrument`等包,我们可以了解引用类型和内存监控的原理,这对于优化程序性能和避免内存泄漏至关重要。...