java中List对象列表实现去重或取出及排序的方法
前言
因为在面试的时候碰到几次list的去重和排序,觉着有必要给大家总结一下具体的方法,分享出来供大家学习参考,话不多说了,来一起看看下面介绍的一种做法:
一、list去重
1.1实体类Student
List
student的equals方法:
publicvoidequals(Objecto){ if(this==o)retuntrue; if(!(oinstanceofStudent))returnfalse; Studentstu=(Studend)o; if(id!=stu.id)returnfalse; if(age!=stu.age)returnfalse; returnname!=null?name.equals(stu.name):stu.name==null; }
这里只要记住宗旨是比较Student的属性即可,如果属性相同则相等。先考虑地址相等,然后类型匹配instanceof。接下来是各种属性,int属性直接双等号比较,String类型需要判断是否为null,如果是null则都是null返回true,如果不是null则比较equals。
student的hashcode方法:
publicinthashCode(){ intresult=id; reuslt=31*id+(name!=null?name.hashCode():0); reuslt=31*age; returnreuslt; }
hashCode是为了hash表计算做辅助,方便快速查找。因此hash算法的结果要尽量的散列。这里用到31,这个31在别的博客中看到的原因是这样的:obj*31==obj<<5-obj.左移5位相当乘以2的5次方,就是32.null的hashCode为空。
通过equals和hashCode的实现可以发现,如果equals为true,则所有属性相同,而属性相同则计算出的hashCode必然相同。然而hashCode相同,属性未必一样,即equals不一定为真。
关于hashCode的价值体现并不在这里,而在于HashMap的实现。HashMap内部是通过链表数组的hash结构来实现的,这里就要用到hashcode。
下面是完整的Student代码:
packagecom.test.arithmetic.listequals; /** *这里id,name,age相同则Student相同, *若有其他相同 *CreatedbyAdministratoron2016/3/29. */ publicclassStudent{ intid; Stringname; intage; publicStudent(intid,Stringname,intage){ this.id=id; this.name=name; this.age=age; } @Override publicbooleanequals(Objecto){ if(this==o)returntrue; if(!(oinstanceofStudent))returnfalse; Studentstudent=(Student)o; if(id!=student.id)returnfalse; if(age!=student.age)returnfalse; returnname!=null?name.equals(student.name):student.name==null; } @Override publicinthashCode(){ intresult=id; result=31*result+(name!=null?name.hashCode():0); result=31*result+age; returnresult; } }
1.2通过HashSet去重
如果你觉得自己可以hold住一个完善的hash算法就可以自己去实现它。这里采用jdk自带的HashSet来完成重复获取。
先放代码:
packagecom.test.arithmetic.listequals; importorg.junit.Assert; importjava.util.*; /** *取出list中重复的Student对象 *CreatedbyAdministratoron2016/3/29. */ publicclassObtainListEquals{ publicstaticvoidmain(String[]args){ //原始数据 Listlist=newArrayList<>(); //重复数据 List list2=newArrayList<>(); //填充 for(inti=0;i<10;i++){ list.add(newStudent(i,"_"+i,18+i)); Randomrandom=newRandom(); if(random.nextBoolean()){ list.add(newStudent(i,"_"+i,18+i)); } } //使用hashset去重复,set为重复的集合,可以通过newArrayList(set)转换成list HashSet set=newHashSet<>(); for(Studentstudent:list){ booleanadd=set.add(student); if(!add){ list2.add(student); } } //比较 Assert.assertEquals(list.size(),list2.size()+set.size()); } }
去重的原理和简单,无论你仅仅是想把重复的丢掉,或者将重复的取出来。这里去掉的是第二次遇到的对象,取出的也是第二次遇到的对象。HashSet中的add方法会返回一个Boolean值,如果插入的值已经存在,则直接返回false。关于hashset的源码放到以后研究。大概的说,是通过HashMap的key来实现的,而HashMap在1.8中改动很大,据说是用红黑树实现的,提高了get的时间复杂度。
二、list对象排序
同样list中存放的是Student对象,我需要一个规则来排序。这个排序的规则这里定义为id的比较大小。参考:java中list排序
2.1Student对象实现Comparable接口
Comparable接口提供一个比较的compareTo(Objecto)方法,通过返回值>0,=0,<0比较大小。这里由于仅仅把id当做比较大小的方法,直接用id做减法,如果是要比较对象,建议套用this.property.compareTo(o.property).
packagecom.test.arithmetic.listequals; /** *这里id,name,age相同则Student相同, *若有其他相同 *CreatedbyAdministratoron2016/3/29. */ publicclassStudentimplementsComparable{ intid; Stringname; intage; publicStudent(intid,Stringname,intage){ this.id=id; this.name=name; this.age=age; } @Override publicbooleanequals(Objecto){ if(this==o)returntrue; if(!(oinstanceofStudent))returnfalse; Studentstudent=(Student)o; if(id!=student.id)returnfalse; if(age!=student.age)returnfalse; returnname!=null?name.equals(student.name):student.name==null; } @Override publicinthashCode(){ intresult=id; result=31*result+(name!=null?name.hashCode():0); result=31*result+age; returnresult; } @Override publicintcompareTo(Studento){ returnthis.id-o.id; } }
通过Collections.sort(list)排序:
packagecom.test.arithmetic.list.sort; importcom.test.arithmetic.list.Student; importorg.junit.Before; importorg.junit.Test; importjava.util.ArrayList; importjava.util.Collections; importjava.util.List; /** *对list中对象排序 *CreatedbyAdministratoron2016/3/29. */ publicclassSortList{ Listlist; @Before publicvoidsetUp(){ list=newArrayList<>(); for(inti=0;i<10;i++){ intv=(int)(Math.random()*100); list.add(newStudent(v,"_"+v,18+v)); } System.out.println("原list:"+list); } //方法一,对象实现Comparable接口 @Test publicvoidbyImplements(){ Collections.sort(list); System.out.println("排序后:"+list); } }
2.2重载sort方法,传入一个比较器
Student类还是未实现Comparable接口之前的:
packagecom.test.arithmetic.list; /** *这里id,name,age相同则Student相同, *若有其他相同 *CreatedbyAdministratoron2016/3/29. */ publicclassStudent{ intid; Stringname; intage; publicStudent(intid,Stringname,intage){ this.id=id; this.name=name; this.age=age; } publicintgetId(){ returnid; } publicStudent(intid){ this.id=id; } @Override publicbooleanequals(Objecto){ if(this==o)returntrue; if(!(oinstanceofStudent))returnfalse; Studentstudent=(Student)o; if(id!=student.id)returnfalse; if(age!=student.age)returnfalse; returnname!=null?name.equals(student.name):student.name==null; } @Override publicinthashCode(){ intresult=id; result=31*result+(name!=null?name.hashCode():0); result=31*result+age; returnresult; } @Override publicStringtoString(){ return"Student{"+ "id="+id+ ",name='"+name+'\''+ ",age="+age+ '}'; } }
在排序的代码出添加排序规则:
packagecom.test.arithmetic.list.sort; importcom.test.arithmetic.list.Student; importorg.junit.Before; importorg.junit.Test; importjava.util.ArrayList; importjava.util.Collections; importjava.util.Comparator; importjava.util.List; /** *对list中对象排序 *CreatedbyAdministratoron2016/3/29. */ publicclassSortList{ Listlist; @Before publicvoidsetUp(){ list=newArrayList<>(); for(inti=0;i<10;i++){ intv=(int)(Math.random()*100); list.add(newStudent(v,"_"+v,18+v)); } System.out.println("原list:"+list); } //方法一,对象实现Comparable接口 @Test publicvoidbyImplements(){ //Collections.sort(list); System.out.println("排序后:"+list); } /*方法二,添加比较器*/ @Test publicvoidbyOverideCompare(){ Collections.sort(list,newComparator (){ @Override publicintcompare(Studento1,Studento2){ returno1.getId()-o2.getId(); } }); System.out.println(list); } }
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。