黑马程序员----------java基础加强之hashSet总结
2014-05-19 00:16
495 查看
----------------------android培训、java培训、期待与您交流!
----------------------
关于Set接口下的hashSet总结。
HashSet的使用一直是令人纠结的问题,所以今天翻了笔记把它总结一下,希望能够给看到的人们提供帮助。
他是java.util包下的,使用他们时一般要重新覆盖hashCode()和equals()方法。
而hashCode()方法覆盖有这么三大原则:
1.一定要让那些我们认为相同的对象返回相同的hashCode值。
2.尽量让那些我们认为不相同的值返回不同的hashCode值。
3.尽量让对象的hashCode值三裂开。
当我们试图把某个类的对象当成 HashMap 的 key,或试图将这个类的对象放入 HashSet 中保存时,重写该类的 equals(Object obj) 方法和 hashCode() 方法很重要,而且这两个方法的返回值必须保持一致:当该类的两个的 hashCode() 返回值相同时,它们通过 equals() 方法比较也应该返回 true。通常来说,所有参与计算 hashCode() 返回值的关键属性,都应该用于作为 equals() 比较的标准。
如下程序就正确重写了 Name 类的 hashCode() 和 equals() 方法,程序如下:
Java代码
class Name
{
private String first;
private String last;
public Name(String first, String last)
{
this.first = first;
this.last = last;
}
// 根据 first 判断两个 Name 是否相等
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o.getClass() == Name.class)
{
Name n = (Name)o;
return n.first.equals(first);
}
return false;
}
// 根据 first 计算 Name 对象的 hashCode() 返回值
public int hashCode()
{
return first.hashCode();
}
public String toString()
{
return "Name[first=" + first + ", last=" + last + "]";
}
}
public class HashSetTest2
{
public static void main(String[] args)
{
HashSet<Name> set = new HashSet<Name>();
set.add(new Name("abc" , "123"));
set.add(new Name("abc" , "456"));
System.out.println(set);
}
}
上面程序中提供了一个 Name 类,该 Name 类重写了 equals() 和 toString() 两个方法,这两个方法都是根据 Name 类的 first 实例变量来判断的,当两个 Name 对象的 first 实例变量相等时,这两个 Name 对象的 hashCode() 返回值也相同,通过 equals() 比较也会返回 true。
程序主方法先将第一个 Name 对象添加到 HashSet 中,该 Name 对象的 first 实例变量值为"abc",接着程序再次试图将一个 first 为"abc"的 Name 对象添加到 HashSet 中,很明显,此时没法将新的 Name 对象添加到该 HashSet 中,因为此处试图添加的 Name 对象的 first 也是" abc",HashSet 会判断此处新增的 Name 对象与原有的 Name 对象相同,因此无法添加进入,程序在①号代码处输出
set 集合时将看到该集合里只包含一个 Name 对象,就是第一个、last 为"123"的 Name 对象。
下面是用eclipse自动生成的代码:
很明显,eclspse想的要比我们想的周全,它的做法是在保证相同对象返回相同哈希值的同时,也尽可能的做到了不同对象返回不同的哈希值。
----------------------android培训、java培训、期待与您交流!
----------------------
----------------------
关于Set接口下的hashSet总结。
HashSet的使用一直是令人纠结的问题,所以今天翻了笔记把它总结一下,希望能够给看到的人们提供帮助。
他是java.util包下的,使用他们时一般要重新覆盖hashCode()和equals()方法。
而hashCode()方法覆盖有这么三大原则:
1.一定要让那些我们认为相同的对象返回相同的hashCode值。
2.尽量让那些我们认为不相同的值返回不同的hashCode值。
3.尽量让对象的hashCode值三裂开。
当我们试图把某个类的对象当成 HashMap 的 key,或试图将这个类的对象放入 HashSet 中保存时,重写该类的 equals(Object obj) 方法和 hashCode() 方法很重要,而且这两个方法的返回值必须保持一致:当该类的两个的 hashCode() 返回值相同时,它们通过 equals() 方法比较也应该返回 true。通常来说,所有参与计算 hashCode() 返回值的关键属性,都应该用于作为 equals() 比较的标准。
如下程序就正确重写了 Name 类的 hashCode() 和 equals() 方法,程序如下:
Java代码
class Name
{
private String first;
private String last;
public Name(String first, String last)
{
this.first = first;
this.last = last;
}
// 根据 first 判断两个 Name 是否相等
public boolean equals(Object o)
{
if (this == o)
{
return true;
}
if (o.getClass() == Name.class)
{
Name n = (Name)o;
return n.first.equals(first);
}
return false;
}
// 根据 first 计算 Name 对象的 hashCode() 返回值
public int hashCode()
{
return first.hashCode();
}
public String toString()
{
return "Name[first=" + first + ", last=" + last + "]";
}
}
public class HashSetTest2
{
public static void main(String[] args)
{
HashSet<Name> set = new HashSet<Name>();
set.add(new Name("abc" , "123"));
set.add(new Name("abc" , "456"));
System.out.println(set);
}
}
上面程序中提供了一个 Name 类,该 Name 类重写了 equals() 和 toString() 两个方法,这两个方法都是根据 Name 类的 first 实例变量来判断的,当两个 Name 对象的 first 实例变量相等时,这两个 Name 对象的 hashCode() 返回值也相同,通过 equals() 比较也会返回 true。
程序主方法先将第一个 Name 对象添加到 HashSet 中,该 Name 对象的 first 实例变量值为"abc",接着程序再次试图将一个 first 为"abc"的 Name 对象添加到 HashSet 中,很明显,此时没法将新的 Name 对象添加到该 HashSet 中,因为此处试图添加的 Name 对象的 first 也是" abc",HashSet 会判断此处新增的 Name 对象与原有的 Name 对象相同,因此无法添加进入,程序在①号代码处输出
set 集合时将看到该集合里只包含一个 Name 对象,就是第一个、last 为"123"的 Name 对象。
下面是用eclipse自动生成的代码:
package TestMath; public class Student { private String name; private int age; @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.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; Student other = (Student) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } }
很明显,eclspse想的要比我们想的周全,它的做法是在保证相同对象返回相同哈希值的同时,也尽可能的做到了不同对象返回不同的哈希值。
----------------------android培训、java培训、期待与您交流!
----------------------
相关文章推荐
- 黑马程序员--Java基础加强--03.代码简化 书写规律II_参数化数据类型【重载】【多态】【泛型】【泛型限定】【个人总结】
- 黑马程序员--Java基础加强--08.【javac兼容编译原则】【可变参数数组编译】【个人总结】
- 黑马程序员--Java基础加强--13.利用反射操作泛型II【TypeVariable】【GenericArrayType】【WildcardType】【Type及其子接口的来历】【个人总结】
- 黑马程序员--Java基础加强--12.利用反射操作泛型I【与反射+泛型相关的接口类型综述】【Type】【ParameterizedType】【个人总结】
- 黑马程序员--Java基础加强--04.代码简化 书写规律III_数组参数【重载】【数组】【可变参数数组】【泛型可变参数数组】【个人总结】
- 黑马程序员——java基础加强高薪技术总结
- 黑马程序员__JAVA基础加强--类加载器和代理总结
- 黑马程序员__关于学习Java基础加强的总结_2
- 黑马程序员--Java基础加强--16.利用反射操作泛型V【通过Constructor反射解析泛型构造方法】【通过Field反射解析泛型成员变量】【个人总结】
- 黑马程序员__关于学习Java基础加强的总结_1
- 黑马程序员----【java基础加强】张孝祥视频总结3
- 黑马程序员--Java基础加强--07.【反射创建对象 操作字段 调用方法的异同】【个人总结】
- 黑马程序员--Java基础加强--10.【PropertyDescriptor操作JavaBean VS 反射操作Java类】【个人总结】
- 黑马程序员--Java基础加强--05.【泛型通配符】【个人总结】
- 黑马程序员----【java基础加强】张孝祥视频总结1
- 黑马程序员--Java基础加强--14.利用反射操作泛型III【解析关于泛型类型的细节信息的获取方法】【Method与泛型相关的方法】【个人总结】
- 黑马程序员--Java基础加强总结
- 黑马程序员--Java基础加强--11.【MyEclipse使用快捷键提取方法的要点】【个人总结】
- 黑马程序员----【java基础加强】张孝祥视频总结2
- 黑马程序员--Java基础加强--02.代码简化 书写规律I_原始数据类型【重载】【多态】【泛型】【泛型限定】【个人总结】