面试碰到几次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对象列表去重或取出以及排序的更多相关文章

  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. [转]Tesseract 3.02中文字库训练

    下载chi_sim.traindata字库下载tesseract-ocr-setup-3.02.02.exe 下载地址:http://code.google.com/p/tesseract-ocr/d ...

  2. Mina入门实例(一)

    mina现在用的很多了,之前也有用到,但是毕竟不熟悉,于是查了一些资料,做了一些总结.看代码是最直观的,比什么长篇大论都要好.不过其中重要的理论,也要理解下. 首先是环境,程序运行需要几个包,这里用m ...

  3. MySQL 权限

    create user创建用户 CREATE USER li@localhost IDENTIFIED BY 'li'; 授予用户li数据库person的所有权限,并允许用户li将数据库person的 ...

  4. SSH实战 · JAVA发送邮件相关

    发送激活邮件 电子邮箱:邮件服务器上的一块空间: 邮件服务器:类比于web服务器(tomcat),有相应的服务器软件: 邮件协议:大公司发送和接收服务器分开,也可以都用一个服务器.           ...

  5. Oracle 中 union 和union all 的简单使用说明

    1.刚刚工作不久,经常接触oracle,但是对oracle很多东西都不是很熟.今天我们来了解一下union和union all的简单使用说明.Union(union all): 指令的目的是将两个 S ...

  6. 【PRINCE2是什么】PRINCE2认证之七大原则(4)

    我们先来回顾一下,PRINCE2七大原则分别是持续的业务验证,经验学习,角色与责任,按阶段管理,例外管理,关注产品,剪裁. 第四个原则:按阶段管理. 阶段管理其实是给高层提供了项目生命周期中相对应的控 ...

  7. [Hadoop大数据]——Hive部署入门教程

    Hive是为了解决hadoop中mapreduce编写困难,提供给熟悉sql的人使用的.只要你对SQL有一定的了解,就能通过Hive写出mapreduce的程序,而不需要去学习hadoop中的api. ...

  8. Session for SSRS Report of Microsoft Dynamics AX

    Session for SSRS Report of Microsoft Dynamics AX 版权声明:本文为博主原创文章,未经博主允许不得转载. Contract •A data contrac ...

  9. Leetcode-463 Island Perimeter

    #463. Island Perimeter You are given a map in form of a two-dimensional integer grid where 1 represe ...

  10. javascript的canvas绘图的基本用法

    <canvas>是HTML里面非常强大的元素,利用它结合js可以实现很多动画效果,大大增强交互性.下面,我想用图文并茂的方式阐述一下canvas的绘图机制的基础内容,话不多说,先上代码: ...