-------android培训、java培训、期待与您交流! ----------
equals()和hashCode()方法详细解析
关于Object类的equals方法的特点:
a) 自反:x.equals(x)应该返回true。
b) 对称性:x.equals(y)为true,那么y.equals(x)也为true。
c) 传递性:x.quals(y)为true,并且y.equals(z)为true,那么x.equals(z)也应该为true。
d) 一致性:x.equals(y)的第一次调用为true,那么x.equals(y)的第二次,第三次,第n次调用也应该为true,前提条件是在比较之前没有修改x也没有修改y。
e) 对于非空引用x,x.equals(null)返回false。
关于Object类的hashCode方法的特点:
a) 在Java应用的一次执行过程当中,对于同一个对象的hashCode方法的多次调用,他们应该返回同样的值(前提是该对象的信息没有发生变化)
b) 对于两个对象来说,如果使用equals方法比较返回true,那么这两个对象的hashCode值一定是相同的。
c) 对于两个对象来说,如果使用equals方法比较返回false,那么这两个对象的hashCode值不要求一定不同(可以相同,可以不同),但是如果不同则可以提高应用的性能。
d) 对于Object类来说,不同的Object对象的hashCode值是不同的(Object类的hashCode值表示的是对象的地址)
HashSet
我们在认识set集合看段代码:
publicclassHashSetTest {
publicstaticvoid main(String[] args) {
HashSet set=newHashSet();
set.add("a");
set.add("b");
set.add("c");
set.add("d");
set.add("a");
System.out.println(set);
}
}
我们将看到打印结果是无序且只有一个a。
我们现在再看看以下代码,来认识下HashSet里面放置的是什么对象?
import java.util.HashSet;
public class HashSetTest2 {
publicstatic void main(String[] args) {
HashSetset=new HashSet();
set.add(newPeople("Tom"));
set.add(newPeople("Tom"));
set.add(newPeople("rose"));
System.out.println(set);
set.clear();//清空之前结果
System.out.println("---------------------");
Peoplep1=new People("zhangsan");
set.add(p1);
set.add(p1);
System.out.println(set);
set.clear();
System.out.println("-------------");
Strings1=new String("java1");
Strings2=new String("java1");
set.add(s1);
set.add(s2);
System.out.println(set);//@1
}
}
class People{
Stringname;
publicPeople(String name){
this.name=name;
}
}
总结,当我们使用HashSet时,hashCode()方法就会得到调用,判断已经存储在集合中的对象的hash Code值是否与增加的对象的hashCode值一致;如果不一致,直接加进去;如果一致的话,再进行equals方法的比较,equals方法如果返回true,表示对象已经加进去了,就不会再增加新的对象,否则加进去。
这时我们知道,判断放进去的东西是不是一样,是由equals和hashCode方法共同判断的。
如以上代码@1处,打印system.out.println(“hash code“+s1.hashCoed==s2.hashCode);打印为真,所以不会放置HashSet集合中。
我们要知道,如果我们重写equals方法,那么也要重写hashCode方法,反之亦然。
例如以下例子:
import java.util.HashSet;
publicclassHashSetTest3 {
publicstaticvoid main(String[] args) {
HashSet set =newHashSet();
set.add(new Student("张三"));
set.add(new Student("张三"));
System.out.println(set);
}
}
class Student{
Stringname;
public Student(String name) {
this.name=name;
}
publicinthashCode(){
returnthis.name.hashCode();
}
publicboolean equals(Object o){
if(this==o){
returntrue;
}
if(o!=null&&oinstanceof Student){
Studentstu =(Student)o;
if(this.name==stu.name){
returntrue;
}
}
returnfalse;
}
}
我们也可以使用eclipse提供给我们的hashCode和equals重写方法,这里就不举例子了。
我们要想取得Set集合里的元素,这里我们介绍下迭代器的概念
迭代器(Iterator)
集合中的迭代器是个接口,是用来遍历集合的,用的频率相当高
Iterator<E>iterator():返回在此 set中的元素上进行迭代的迭代器。返回的元素没有特定的顺序(除非此 set是某个提供顺序保证的类的实例)。
接口迭代器有几种方法呢?我们最常用的两种方法:
a) booleanhasNext():如果仍有元素可以迭代,则返回 true。(换句话说,如果 next返回了元素而不是抛出异常,则返回 true)。
b) E next():返回迭代的下一个元素。
下面通过代码来看看具体用法:
import java.util.HashSet;
import java.util.Iterator;
publicclassIteratorTest {
publicstaticvoid main(String[] args) {
HashSetset=newHashSet();
set.add("hello");
set.add(" world");
set.add(" welcome");
Iteratorit=set.iterator();//使用迭代器方法
while(it.hasNext()){ //判断是true,如果是一直循环。
Stringstr=(String) it.next();//获得下个元素,并赋给String类型
System.out.print(str);
}
//使用for循环来写
System.out.println("----------------------");
for(Iterator it1=set.iterator();it1.hasNext();){//最后什么++或--都不用写
String str=(String) it1.next();
System.out.print(str);
}
}
}
TreeSet
TreeSet实现了sortedSet接口,sortedSet是Set接口的子接口,TreeSet是具有排序的功能,默认是从小到大进行排序。我们来看看TreeSet的如下代码:
import java.util.TreeSet;
publicclassTreeSetTest1 {
publicstaticvoid main(String[] args) {
TreeSetset=newTreeSet();
set.add("c");
set.add("a");
set.add("f");
set.add("e");
set.add("b");
//打印[a, b, c, e, f]
System.out.println(set);
}
}
那么,我们如果要对集合类元素进行反向排序呢?这里我们就要实现Comparator接口,下面我们来看看如何将set集合进行反向排序呢?看如下代码
import java.util.Comparator;
import java.util.Iterator;
import java.util.TreeSet;
publicclassComparatTest {
publicstaticvoidmain(String[] args) {
TreeSetset=newTreeSet(new CompareFor());//根据TreeSet的另一种构造方法
set.add("A");
set.add("B");
set.add("C");
set.add("D");
set.add("E");
set.add("F");
for(Iteratorit=set.iterator();it.hasNext();){
Stringvalue=(String) it.next();
System.out.println(value);
}
}
}
class CompareForimplementsComparator{
publicint compare(Object o1,Object o2) {
Strings1=(String) o1;
Strings2=(String) o2;
return s2.compareTo(s1);//o2-o1=1(正整数),此处调用String类的compareTo方法
}
}
Collections
Collection是一个接口,而加上一个s就Collections类,那么这个类在集合中的作用是什么呢?这个类在就是对集合操作的一个类,就像Arrays类对数组的操作一样,下面我们来看看Collections在集合中是怎么使用的?
下面我们列举下Collections常用的方法:
a) 反向排序:publicstatic <T> Comparator<T> reverseOrder():返回一个比较器,它强行逆转指定比较器的顺序
b)排序:lic static <T> voidsort(List<T> list,Comparator<? super T> c):根据指定比较器产生的顺序对指定列表进行排序。
c)随机(打乱顺序):public static void shuffle(List<?> list):使用默认随机源对指定列表进行置换。所有置换发生的可能性都是大致相等的。
d)最大值:public static max(Collectionc):根据元素的自然顺序,返回给定 collection的最大元素
e)最小值:public static min(Collection c):根据指定比较器产生的顺序,返回给定 collection的最小元素
我们现在通过代码来看看这些方法是怎么用的:
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
publicclassCollectionsTest {
publicstaticvoid main(String[] args) {
LinkedListlist =newLinkedList();
list.add(20);
list.add(-8);
list.add(-20);
list.add(8);
Comparatorr=Collections.reverseOrder();//使用Collection方法中反向排序
Collections.sort(list,r);//排序方法
for(Iteratorit=list.iterator();it.hasNext();){
Integeri=(Integer) it.next();
System.out.print(i+" ");
}
System.out.println();//换行
System.out.println("--------------------------------");
Collections.shuffle(list);
for(Iteratorit=list.iterator();it.hasNext();){
Integeri=(Integer) it.next();
System.out.print(i+" ");
}
System.out.println();//换行
System.out.println("----------------------");
System.out.println("最大值"+Collections.max(list));
System.out.println("最小值"+Collections.min(list));
}
}