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 ...
随机推荐
- [转]Tesseract 3.02中文字库训练
下载chi_sim.traindata字库下载tesseract-ocr-setup-3.02.02.exe 下载地址:http://code.google.com/p/tesseract-ocr/d ...
- Mina入门实例(一)
mina现在用的很多了,之前也有用到,但是毕竟不熟悉,于是查了一些资料,做了一些总结.看代码是最直观的,比什么长篇大论都要好.不过其中重要的理论,也要理解下. 首先是环境,程序运行需要几个包,这里用m ...
- MySQL 权限
create user创建用户 CREATE USER li@localhost IDENTIFIED BY 'li'; 授予用户li数据库person的所有权限,并允许用户li将数据库person的 ...
- SSH实战 · JAVA发送邮件相关
发送激活邮件 电子邮箱:邮件服务器上的一块空间: 邮件服务器:类比于web服务器(tomcat),有相应的服务器软件: 邮件协议:大公司发送和接收服务器分开,也可以都用一个服务器. ...
- Oracle 中 union 和union all 的简单使用说明
1.刚刚工作不久,经常接触oracle,但是对oracle很多东西都不是很熟.今天我们来了解一下union和union all的简单使用说明.Union(union all): 指令的目的是将两个 S ...
- 【PRINCE2是什么】PRINCE2认证之七大原则(4)
我们先来回顾一下,PRINCE2七大原则分别是持续的业务验证,经验学习,角色与责任,按阶段管理,例外管理,关注产品,剪裁. 第四个原则:按阶段管理. 阶段管理其实是给高层提供了项目生命周期中相对应的控 ...
- [Hadoop大数据]——Hive部署入门教程
Hive是为了解决hadoop中mapreduce编写困难,提供给熟悉sql的人使用的.只要你对SQL有一定的了解,就能通过Hive写出mapreduce的程序,而不需要去学习hadoop中的api. ...
- Session for SSRS Report of Microsoft Dynamics AX
Session for SSRS Report of Microsoft Dynamics AX 版权声明:本文为博主原创文章,未经博主允许不得转载. Contract •A data contrac ...
- Leetcode-463 Island Perimeter
#463. Island Perimeter You are given a map in form of a two-dimensional integer grid where 1 represe ...
- javascript的canvas绘图的基本用法
<canvas>是HTML里面非常强大的元素,利用它结合js可以实现很多动画效果,大大增强交互性.下面,我想用图文并茂的方式阐述一下canvas的绘图机制的基础内容,话不多说,先上代码: ...