java中List对象列表去重或取出以及排序
面试碰到几次list的去重和排序。下面介绍一种做法:
1. list去重
1.1 实体类Student
List<Student>容量10k以上,要求去重复。这里Student的重复标准是属性相同,因此需要重写equals和hashcode方法,不知道有几个可以手写出来。
student的equals方法:
- public void equals(Object o){
- if(this == o) retun true;
- if(!(o instanceof Student)) return false;
- Student stu = (Studend)o;
- if(id!=stu.id) return false;
- if(age!=stu.age) return false;
- return name!=null ? name.equals(stu.name) : stu.name ==null;
- }
这里只要记住宗旨是比较Student的属性即可,如果属性相同则相等。先考虑地址相等,然后类型匹配instanceof。接下来是各种属性,int属性直接双等号比较,String类型需要判断是否为null,如果是null则都是null返回true,如果不是null则比较equals。
student的hashcode方法:
- public int hashCode(){
- int result = id;
- reuslt = 31*id +(name!=null?name.hashCode():0);
- reuslt = 31*age;
- return reuslt;
- }
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代码:
- package com.test.arithmetic.listequals;
- /**
- * 这里id,name,age相同则Student相同,
- * 若有其他相同
- * Created by Administrator on 2016/3/29.
- */
- public class Student {
- int id;
- String name;
- int age;
- public Student(int id, String name, int age) {
- this.id = id;
- this.name = name;
- this.age = age;
- }
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof Student)) return false;
- Student student = (Student) o;
- if (id != student.id) return false;
- if (age != student.age) return false;
- return name != null ? name.equals(student.name) : student.name == null;
- }
- @Override
- public int hashCode() {
- int result = id;
- result = 31 * result + (name != null ? name.hashCode() : 0);
- result = 31 * result + age;
- return result;
- }
- }
1.2通过HashSet去重
如果你觉得自己可以hold住一个完善的hash算法就可以自己去实现它。这里采用jdk自带的HashSet来完成重复获取。
先放代码:
- package com.test.arithmetic.listequals;
- import org.junit.Assert;
- import java.util.*;
- /**
- * 取出list中重复的Student对象
- * Created by Administrator on 2016/3/29.
- */
- public class ObtainListEquals {
- public static void main(String[] args){
- //原始数据
- List<Student> list = new ArrayList<>();
- //重复数据
- List<Student> list2 = new ArrayList<>();
- //填充
- for (int i = 0; i < 10 ; i++) {
- list.add(new Student(i,"_"+i,18+i));
- Random random = new Random();
- if (random.nextBoolean()){
- list.add(new Student(i,"_"+i,18+i));
- }
- }
- //使用hashset去重复,set为重复的集合,可以通过new ArrayList(set)转换成list
- HashSet<Student> set = new HashSet<>();
- for (Student student : list) {
- boolean add = 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的时间复杂度。参考: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).
- package com.test.arithmetic.listequals;
- /**
- * 这里id,name,age相同则Student相同,
- * 若有其他相同
- * Created by Administrator on 2016/3/29.
- */
- public class Student implements Comparable<Student>{
- int id;
- String name;
- int age;
- public Student(int id, String name, int age) {
- this.id = id;
- this.name = name;
- this.age = age;
- }
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof Student)) return false;
- Student student = (Student) o;
- if (id != student.id) return false;
- if (age != student.age) return false;
- return name != null ? name.equals(student.name) : student.name == null;
- }
- @Override
- public int hashCode() {
- int result = id;
- result = 31 * result + (name != null ? name.hashCode() : 0);
- result = 31 * result + age;
- return result;
- }
- @Override
- public int compareTo(Student o) {
- return this.id-o.id;
- }
- }
通过Collections.sort(list)排序:
- package com.test.arithmetic.list.sort;
- import com.test.arithmetic.list.Student;
- import org.junit.Before;
- import org.junit.Test;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.List;
- /**
- * 对list中对象排序
- * Created by Administrator on 2016/3/29.
- */
- public class SortList {
- List<Student> list;
- @Before
- public void setUp(){
- list = new ArrayList<>();
- for (int i = 0; i < 10; i++) {
- int v = (int)(Math.random() * 100);
- list.add(new Student(v,"_"+v,18+v));
- }
- System.out.println("原list:"+list);
- }
- //方法一,对象实现Comparable接口
- @Test
- public void byImplements(){
- Collections.sort(list);
- System.out.println("排序后:"+list);
- }
- }
2.2 重载sort方法,传入一个比较器
Student类还是未实现Comparable接口之前的:
- package com.test.arithmetic.list;
- /**
- * 这里id,name,age相同则Student相同,
- * 若有其他相同
- * Created by Administrator on 2016/3/29.
- */
- public class Student{
- int id;
- String name;
- int age;
- public Student(int id, String name, int age) {
- this.id = id;
- this.name = name;
- this.age = age;
- }
- public int getId() {
- return id;
- }
- public Student(int id) {
- this.id = id;
- }
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (!(o instanceof Student)) return false;
- Student student = (Student) o;
- if (id != student.id) return false;
- if (age != student.age) return false;
- return name != null ? name.equals(student.name) : student.name == null;
- }
- @Override
- public int hashCode() {
- int result = id;
- result = 31 * result + (name != null ? name.hashCode() : 0);
- result = 31 * result + age;
- return result;
- }
- @Override
- public String toString() {
- return "Student{" +
- "id=" + id +
- ", name='" + name + '\'' +
- ", age=" + age +
- '}';
- }
- }
在排序的代码出添加排序规则:
- package com.test.arithmetic.list.sort;
- import com.test.arithmetic.list.Student;
- import org.junit.Before;
- import org.junit.Test;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.Comparator;
- import java.util.List;
- /**
- * 对list中对象排序
- * Created by Administrator on 2016/3/29.
- */
- public class SortList {
- List<Student> list;
- @Before
- public void setUp(){
- list = new ArrayList<>();
- for (int i = 0; i < 10; i++) {
- int v = (int)(Math.random() * 100);
- list.add(new Student(v,"_"+v,18+v));
- }
- System.out.println("原list:"+list);
- }
- //方法一,对象实现Comparable接口
- @Test
- public void byImplements(){
- // Collections.sort(list);
- System.out.println("排序后:"+list);
- }
- /*方法二,添加比较器*/
- @Test
- public void byOverideCompare(){
- Collections.sort(list, new Comparator<Student>() {
- @Override
- public int compare(Student o1, Student o2) {
- return o1.getId()-o2.getId();
- }
- });
- System.out.println(list);
- }
- }
java中List对象列表去重或取出以及排序的更多相关文章
- JAVA中JavaBean对象之间属性拷贝的方法
JAVA中JavaBean对象之间的拷贝通常是用get/set方法,但如果你有两个属性相同的JavaBean或有大部分属性相同的JavaBean,对于这种情况,可以采用以下几个简便方法处理. 下面对这 ...
- JAVA中List对象去除重复值的方法
JAVA中List对象去除重复值,大致分为两种情况,一种是List<String>.List<Integer>这类,直接根据List中的值进行去重,另一种是List<Us ...
- 浅谈Java中的对象和引用
浅谈Java中的对象和对象引用 在Java中,有一组名词经常一起出现,它们就是“对象和对象引用”,很多朋友在初学Java的时候可能经常会混淆这2个概念,觉得它们是一回事,事实上则不然.今天我们就来一起 ...
- 【译】Java中的对象序列化
前言 好久没翻译simple java了,睡前来一篇. 译文链接: http://www.programcreek.com/2014/01/java-serialization/ 什么是对象序列化 在 ...
- java中直接打印对象
java中直接打印对象,会调用对象.toString()方法.如果没有重写toString()方法会输出"类名+@+hasCode"值,hasCode是一个十六进制数 //没有重写 ...
- 如何使用java中的对象
使用java中的对象,分2步: 1.创建一个对象: 2.使用对象的属性和方法. 见下面的示例代码: package com.imooc; //1.定义一个类 public class Telphone ...
- Java中String对象的不可变性
首先看一个程序 package reverse; public class Reverse { public static void main(String[] args) { String c1=n ...
- java中把list列表转为arrayList以及arraylist数组截取的简单方法
java中把list列表转为arrayList以及arraylist数组截取的简单方法 package xiaobai; import java.util.ArrayList; import java ...
- JAVA中JavaBean对象之间拷贝的方法
JAVA中JavaBean对象之间的拷贝通常是用get/set方法,但如果你有两个属性相同的JavaBean或有大部分属性相同的JavaBean,有个更简便的方法,他们之间的拷贝可以通过copyPro ...
随机推荐
- mysql之触发器trigger
触发器(trigger):监视某种情况,并触发某种操作. 触发器创建语法四要素:1.监视地点(table) 2.监视事件(insert/update/delete) 3.触发时间(after/befo ...
- 建模元件有哪些在MapleSim中
信号库:包含通用信号模块.布尔.控制器.离散信号模块.信号源.线性信号模块.非线性信号模块.时间离散信号模块.查询表.信号转换器.数学运算.关系元件.特殊信号模块,应用案例. 电子库:包含电阻.运算放 ...
- CSS 使用母版页的内容页如何调用css和javascript
方案一: 把所有的css样式和javascript函数放到母版页的<head></head>中,我觉得这样做的弊端就是导致母版页的<head></head&g ...
- 导向矢量(Steering Vector)
导向矢量是阵列天线的所有阵元对具有单位能量窄带信源的响应. 由于阵列响应在不同方向上是不同的,导向矢量与信源的方向是相互关联的,这种关联的独特性依赖于阵列的几何结构.对于同一阵元阵列,导向矢量的每一个 ...
- CYQ.Data+EasyUI开发:几个相关的问题CheckBox、Tree、TreeGrid
前言: 话说到新的公司已经呆了三个星期了,从上班的第二天开始就一直在写项目文档和给开发人员培训,以至于我的QQ签名从"我不是来搞培训的“到最后直接换成”我是来搞培训的“. 虽然挂名开发经理, ...
- Backbone源码分析(二)
在传统MVC框架模式中,Model承担业务逻辑的任务.Backbone作为一个mvc框架,主要的业务逻辑交由Model与Collection来实现.Model代表领域对象,今天主要学一下Model源码 ...
- 剑指Offer面试题:29.丑数
一.题目:丑数 题目:我们把只包含因子2.3和5的数称作丑数(Ugly Number).求按从小到大的顺序的第1500个丑数.例如6.8都是丑数,但14不是,因为它包含因子7.习惯上我们把1当做第一个 ...
- APOC 15 Years Celebration
最近很忙,没有及时更新博客,也没有参加各种活动,唯一的活动就是接下来要讲的APOC 15 Years Celebration.不知不觉,自己也加入APOC有一年多了,正如大家所说“岁月是把杀猪刀”,我 ...
- Linux更改用户密码
登录虚拟机后,使用passwd密令更改用户密码,新密码需要输入两次才能更改成功.不多说,直接上代码 [root@localhost Desktop]# passwd //使用passwd密令 Chan ...
- Knockout中文开发指南(完整版API中文文档) 目录索引
a, .tree li > span { padding: 4pt; border-radius: 4px; } .tree li a { color:#46cfb0; text-decorat ...