面试碰到几次list的去重和排序。下面介绍一种做法:

1. list去重

1.1 实体类Student

List<Student>容量10k以上,要求去重复。这里Student的重复标准是属性相同,因此需要重写equals和hashcode方法,不知道有几个可以手写出来。

student的equals方法:

  1. public void equals(Object o){
  2. if(this == o) retun true;
  3. if(!(o instanceof Student)) return false;
  4. Student stu = (Studend)o;
  5. if(id!=stu.id) return false;
  6. if(age!=stu.age) return false;
  7. return name!=null ? name.equals(stu.name) : stu.name ==null;
  8. }

这里只要记住宗旨是比较Student的属性即可,如果属性相同则相等。先考虑地址相等,然后类型匹配instanceof。接下来是各种属性,int属性直接双等号比较,String类型需要判断是否为null,如果是null则都是null返回true,如果不是null则比较equals。

student的hashcode方法:

  1. public int hashCode(){
  2. int result = id;
  3. reuslt = 31*id +(name!=null?name.hashCode():0);
  4. reuslt = 31*age;
  5. return reuslt;
  6. }

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代码:

  1. package com.test.arithmetic.listequals;
  2.  
  3. /**
  4. * 这里id,name,age相同则Student相同,
  5. * 若有其他相同
  6. * Created by Administrator on 2016/3/29.
  7. */
  8. public class Student {
  9. int id;
  10. String name;
  11. int age;
  12.  
  13. public Student(int id, String name, int age) {
  14. this.id = id;
  15. this.name = name;
  16. this.age = age;
  17. }
  18.  
  19. @Override
  20. public boolean equals(Object o) {
  21. if (this == o) return true;
  22. if (!(o instanceof Student)) return false;
  23.  
  24. Student student = (Student) o;
  25.  
  26. if (id != student.id) return false;
  27. if (age != student.age) return false;
  28. return name != null ? name.equals(student.name) : student.name == null;
  29.  
  30. }
  31.  
  32. @Override
  33. public int hashCode() {
  34. int result = id;
  35. result = 31 * result + (name != null ? name.hashCode() : 0);
  36. result = 31 * result + age;
  37. return result;
  38. }
  39.  
  40. }

1.2通过HashSet去重

如果你觉得自己可以hold住一个完善的hash算法就可以自己去实现它。这里采用jdk自带的HashSet来完成重复获取。

先放代码:

  1. package com.test.arithmetic.listequals;
  2. import org.junit.Assert;
  3.  
  4. import java.util.*;
  5.  
  6. /**
  7. * 取出list中重复的Student对象
  8. * Created by Administrator on 2016/3/29.
  9. */
  10. public class ObtainListEquals {
  11. public static void main(String[] args){
  12. //原始数据
  13. List<Student> list = new ArrayList<>();
  14. //重复数据
  15. List<Student> list2 = new ArrayList<>();
  16. //填充
  17. for (int i = 0; i < 10 ; i++) {
  18. list.add(new Student(i,"_"+i,18+i));
  19. Random random = new Random();
  20. if (random.nextBoolean()){
  21. list.add(new Student(i,"_"+i,18+i));
  22. }
  23. }
  24. //使用hashset去重复,set为重复的集合,可以通过new ArrayList(set)转换成list
  25. HashSet<Student> set = new HashSet<>();
  26. for (Student student : list) {
  27. boolean add = set.add(student);
  28. if (!add){
  29. list2.add(student);
  30. }
  31. }
  32. //比较
  33. Assert.assertEquals(list.size(),list2.size()+set.size());
  34.  
  35. }
  36.  
  37. }

去重的原理和简单,无论你仅仅是想把重复的丢掉,或者将重复的取出来。这里去掉的是第二次遇到的对象,取出的也是第二次遇到的对象。HashSet中的add方法会返回一个Boolean值,如果插入的值已经存在,则直接返回false。关于hashset的源码放到以后研究。大概的说,是通过HashMap的key来实现的,而HashMap在1.8中改动很大,据说是用红黑树实现的,提高了get的时间复杂度。参考:1.8HashMap

2. list对象排序

同样list中存放的是Student对象,我需要一个规则来排序。这个排序的规则这里定义为id的比较大小。参考:java中list排序

2.1 Student对象实现Comparable接口

Comparable接口提供一个比较的compareTo(Object o)方法,通过返回值>0,=0,<0比较大小。这里由于仅仅把id当做比较大小的方法,直接用id做减法,如果是要比较对象,建议套用this.property.compareTo(o.property).

  1. package com.test.arithmetic.listequals;
  2.  
  3. /**
  4. * 这里id,name,age相同则Student相同,
  5. * 若有其他相同
  6. * Created by Administrator on 2016/3/29.
  7. */
  8. public class Student implements Comparable<Student>{
  9. int id;
  10. String name;
  11. int age;
  12.  
  13. public Student(int id, String name, int age) {
  14. this.id = id;
  15. this.name = name;
  16. this.age = age;
  17. }
  18.  
  19. @Override
  20. public boolean equals(Object o) {
  21. if (this == o) return true;
  22. if (!(o instanceof Student)) return false;
  23.  
  24. Student student = (Student) o;
  25.  
  26. if (id != student.id) return false;
  27. if (age != student.age) return false;
  28. return name != null ? name.equals(student.name) : student.name == null;
  29.  
  30. }
  31.  
  32. @Override
  33. public int hashCode() {
  34. int result = id;
  35. result = 31 * result + (name != null ? name.hashCode() : 0);
  36. result = 31 * result + age;
  37. return result;
  38. }
  39.  
  40. @Override
  41. public int compareTo(Student o) {
  42. return this.id-o.id;
  43. }
  44. }

通过Collections.sort(list)排序:

  1. package com.test.arithmetic.list.sort;
  2.  
  3. import com.test.arithmetic.list.Student;
  4. import org.junit.Before;
  5. import org.junit.Test;
  6.  
  7. import java.util.ArrayList;
  8. import java.util.Collections;
  9. import java.util.List;
  10.  
  11. /**
  12. * 对list中对象排序
  13. * Created by Administrator on 2016/3/29.
  14. */
  15. public class SortList {
  16. List<Student> list;
  17. @Before
  18. public void setUp(){
  19. list = new ArrayList<>();
  20. for (int i = 0; i < 10; i++) {
  21. int v = (int)(Math.random() * 100);
  22. list.add(new Student(v,"_"+v,18+v));
  23. }
  24. System.out.println("原list:"+list);
  25. }
  26. //方法一,对象实现Comparable接口
  27. @Test
  28. public void byImplements(){
  29. Collections.sort(list);
  30. System.out.println("排序后:"+list);
  31. }
  32. }

2.2 重载sort方法,传入一个比较器

Student类还是未实现Comparable接口之前的:

  1. package com.test.arithmetic.list;
  2.  
  3. /**
  4. * 这里id,name,age相同则Student相同,
  5. * 若有其他相同
  6. * Created by Administrator on 2016/3/29.
  7. */
  8. public class Student{
  9. int id;
  10. String name;
  11. int age;
  12.  
  13. public Student(int id, String name, int age) {
  14. this.id = id;
  15. this.name = name;
  16. this.age = age;
  17. }
  18.  
  19. public int getId() {
  20. return id;
  21. }
  22.  
  23. public Student(int id) {
  24. this.id = id;
  25. }
  26.  
  27. @Override
  28. public boolean equals(Object o) {
  29. if (this == o) return true;
  30. if (!(o instanceof Student)) return false;
  31.  
  32. Student student = (Student) o;
  33.  
  34. if (id != student.id) return false;
  35. if (age != student.age) return false;
  36. return name != null ? name.equals(student.name) : student.name == null;
  37.  
  38. }
  39.  
  40. @Override
  41. public int hashCode() {
  42. int result = id;
  43. result = 31 * result + (name != null ? name.hashCode() : 0);
  44. result = 31 * result + age;
  45. return result;
  46. }
  47.  
  48. @Override
  49. public String toString() {
  50. return "Student{" +
  51. "id=" + id +
  52. ", name='" + name + '\'' +
  53. ", age=" + age +
  54. '}';
  55. }
  56. }

在排序的代码出添加排序规则:

  1. package com.test.arithmetic.list.sort;
  2.  
  3. import com.test.arithmetic.list.Student;
  4. import org.junit.Before;
  5. import org.junit.Test;
  6.  
  7. import java.util.ArrayList;
  8. import java.util.Collections;
  9. import java.util.Comparator;
  10. import java.util.List;
  11.  
  12. /**
  13. * 对list中对象排序
  14. * Created by Administrator on 2016/3/29.
  15. */
  16. public class SortList {
  17. List<Student> list;
  18. @Before
  19. public void setUp(){
  20. list = new ArrayList<>();
  21. for (int i = 0; i < 10; i++) {
  22. int v = (int)(Math.random() * 100);
  23. list.add(new Student(v,"_"+v,18+v));
  24. }
  25. System.out.println("原list:"+list);
  26. }
  27. //方法一,对象实现Comparable接口
  28. @Test
  29. public void byImplements(){
  30. // Collections.sort(list);
  31. System.out.println("排序后:"+list);
  32. }
  33.  
  34. /*方法二,添加比较器*/
  35. @Test
  36. public void byOverideCompare(){
  37.  
  38. Collections.sort(list, new Comparator<Student>() {
  39. @Override
  40. public int compare(Student o1, Student o2) {
  41. return o1.getId()-o2.getId();
  42. }
  43. });
  44. System.out.println(list);
  45. }
  46. }

java中List对象列表去重或取出以及排序的更多相关文章

  1. JAVA中JavaBean对象之间属性拷贝的方法

    JAVA中JavaBean对象之间的拷贝通常是用get/set方法,但如果你有两个属性相同的JavaBean或有大部分属性相同的JavaBean,对于这种情况,可以采用以下几个简便方法处理. 下面对这 ...

  2. JAVA中List对象去除重复值的方法

    JAVA中List对象去除重复值,大致分为两种情况,一种是List<String>.List<Integer>这类,直接根据List中的值进行去重,另一种是List<Us ...

  3. 浅谈Java中的对象和引用

    浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...

  4. 【译】Java中的对象序列化

    前言 好久没翻译simple java了,睡前来一篇. 译文链接: http://www.programcreek.com/2014/01/java-serialization/ 什么是对象序列化 在 ...

  5. java中直接打印对象

    java中直接打印对象,会调用对象.toString()方法.如果没有重写toString()方法会输出"类名+@+hasCode"值,hasCode是一个十六进制数 //没有重写 ...

  6. 如何使用java中的对象

    使用java中的对象,分2步: 1.创建一个对象: 2.使用对象的属性和方法. 见下面的示例代码: package com.imooc; //1.定义一个类 public class Telphone ...

  7. Java中String对象的不可变性

    首先看一个程序 package reverse; public class Reverse { public static void main(String[] args) { String c1=n ...

  8. java中把list列表转为arrayList以及arraylist数组截取的简单方法

    java中把list列表转为arrayList以及arraylist数组截取的简单方法 package xiaobai; import java.util.ArrayList; import java ...

  9. JAVA中JavaBean对象之间拷贝的方法

    JAVA中JavaBean对象之间的拷贝通常是用get/set方法,但如果你有两个属性相同的JavaBean或有大部分属性相同的JavaBean,有个更简便的方法,他们之间的拷贝可以通过copyPro ...

随机推荐

  1. mysql之触发器trigger

    触发器(trigger):监视某种情况,并触发某种操作. 触发器创建语法四要素:1.监视地点(table) 2.监视事件(insert/update/delete) 3.触发时间(after/befo ...

  2. 建模元件有哪些在MapleSim中

    信号库:包含通用信号模块.布尔.控制器.离散信号模块.信号源.线性信号模块.非线性信号模块.时间离散信号模块.查询表.信号转换器.数学运算.关系元件.特殊信号模块,应用案例. 电子库:包含电阻.运算放 ...

  3. CSS 使用母版页的内容页如何调用css和javascript

    方案一: 把所有的css样式和javascript函数放到母版页的<head></head>中,我觉得这样做的弊端就是导致母版页的<head></head&g ...

  4. 导向矢量(Steering Vector)

    导向矢量是阵列天线的所有阵元对具有单位能量窄带信源的响应. 由于阵列响应在不同方向上是不同的,导向矢量与信源的方向是相互关联的,这种关联的独特性依赖于阵列的几何结构.对于同一阵元阵列,导向矢量的每一个 ...

  5. CYQ.Data+EasyUI开发:几个相关的问题CheckBox、Tree、TreeGrid

    前言: 话说到新的公司已经呆了三个星期了,从上班的第二天开始就一直在写项目文档和给开发人员培训,以至于我的QQ签名从"我不是来搞培训的“到最后直接换成”我是来搞培训的“. 虽然挂名开发经理, ...

  6. Backbone源码分析(二)

    在传统MVC框架模式中,Model承担业务逻辑的任务.Backbone作为一个mvc框架,主要的业务逻辑交由Model与Collection来实现.Model代表领域对象,今天主要学一下Model源码 ...

  7. 剑指Offer面试题:29.丑数

    一.题目:丑数 题目:我们把只包含因子2.3和5的数称作丑数(Ugly Number).求按从小到大的顺序的第1500个丑数.例如6.8都是丑数,但14不是,因为它包含因子7.习惯上我们把1当做第一个 ...

  8. APOC 15 Years Celebration

    最近很忙,没有及时更新博客,也没有参加各种活动,唯一的活动就是接下来要讲的APOC 15 Years Celebration.不知不觉,自己也加入APOC有一年多了,正如大家所说“岁月是把杀猪刀”,我 ...

  9. Linux更改用户密码

    登录虚拟机后,使用passwd密令更改用户密码,新密码需要输入两次才能更改成功.不多说,直接上代码 [root@localhost Desktop]# passwd //使用passwd密令 Chan ...

  10. Knockout中文开发指南(完整版API中文文档) 目录索引

    a, .tree li > span { padding: 4pt; border-radius: 4px; } .tree li a { color:#46cfb0; text-decorat ...