java list去重操作实现方式

 更新时间:2012年12月05日 15:57:46   作者:  
Java中的List是可以包含重复元素的(hash code 和equals),接下来将介绍两种方式实现java list去重操作,感兴趣的朋友可以参考下
Java中的List是可以包含重复元素的(hash code 和equals),那么对List进行去重操作有两种方式实现:
方案一:可以通过HashSet来实现,代码如下:
复制代码 代码如下:

class Student {
private String id;
private String name;
public Student(String id, String name) {
super();
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + "]";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((id == null) ? 0 : id.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
Student other = (Student) obj;
if (id == null) {
if (other.id != null) {
return false;
}
} else if (!id.equals(other.id)) {
return false;
}
if (name == null) {
if (other.name != null) {
return false;
}
} else if (!name.equals(other.name)) {
return false;
}
return true;
}
}

必须实现hashCode和equals两个方法,一会我们会看为啥必须实现
具体的操作代码如下:
复制代码 代码如下:

private static void removeListDuplicateObject() {
List<Student> list = new ArrayList<Student>();
for (int i = 0; i < 10; i++) {
Student student = new Student("id", "name");
list.add(student);
}
System.out.println(Arrays.toString(list.toArray()));
Set<Student> set = new HashSet<Student>();
set.addAll(list);
System.out.println(Arrays.toString(set.toArray()));
list.removeAll(list);
set.removeAll(set);
System.out.println(Arrays.toString(list.toArray()));
System.out.println(Arrays.toString(set.toArray()));
}

调用代码:
复制代码 代码如下:

public static void main(String[] args) {
removeListDuplicateObject();
}

利用HashSet进行去重操作,为啥必须覆盖hashCode和equals两个方法呢?
我们查看HashSet的add操作源码如下:
复制代码 代码如下:

public boolean add(E e) {
return map.put(e, PRESENT)==null;
}

调用了HashMap进行操作的,我们看HashMap的put操作:
复制代码 代码如下:

public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}

需要注意的是:
复制代码 代码如下:

if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
......
}

也就是说hash code相等且equals(==)。
复杂度:一边遍历即可,O(n)
方案二:直接遍历一遍List进行通过contains和add操作实现
代码如下:
复制代码 代码如下:

private static void removeListDuplicateObjectByList() {
List<Student> list = new ArrayList<Student>();
for (int i = 0; i < 10; i++) {
Student student = new Student("id", "name");
list.add(student);
}
System.out.println(Arrays.toString(list.toArray()));
List<Student> listUniq = new ArrayList<Student>();
for (Student student : list) {
if (!listUniq.contains(student)) {
listUniq.add(student);
}
}
System.out.println(Arrays.toString(listUniq.toArray()));
list.removeAll(list);
listUniq.removeAll(listUniq);
System.out.println(Arrays.toString(list.toArray()));
System.out.println(Arrays.toString(listUniq.toArray()));
}

其他等同上面。
复杂度:
一边遍历,同时调用了contains方法,我们查看源码如下:
复制代码 代码如下:

public boolean contains(Object o) {
return indexOf(o) >= 0;
}
public int indexOf(Object o) {
if (o == null) {
for (int i = 0; i < size; i++)
if (elementData[i]==null)
return i;
} else {
for (int i = 0; i < size; i++)
if (o.equals(elementData[i]))
return i;
}
return -1;
}

可以看到又对新的list做了一次遍历操作。也就是1+2+....+n这样复杂度为O(n*n)
结论:
方案一效率高,即采用HashSet的方式进行去重操作

相关文章

  • Java 同步锁(synchronized)详解及实例

    Java 同步锁(synchronized)详解及实例

    这篇文章主要介绍了Java 同步锁(synchronized)详解及实例的相关资料,需要的朋友可以参考下
    2017-03-03
  • MybatisPlus #{param}和${param}的用法详解

    MybatisPlus #{param}和${param}的用法详解

    这篇文章主要介绍了MybatisPlus #{param}和${param}的用法详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • Java线程协作的两种方式小结

    Java线程协作的两种方式小结

    Java中线程协作的最常见的两种方式是利用Object.wait()、Object.notify()和使用Condition,本文主要介绍了Java线程协作的两种方式小结,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
    2023-05-05
  • 详解JAVA 时间处理相关类

    详解JAVA 时间处理相关类

    这篇文章主要介绍了JAVA 时间处理相关类的知识,文中示例代码非常详细,供大家参考和学习,感兴趣的朋友可以了解下
    2020-06-06
  • Java枚举类型enum的详解及使用

    Java枚举类型enum的详解及使用

    这篇文章主要介绍了Java枚举类型enum的详解及使用的相关资料,需要的朋友可以参考下
    2017-05-05
  • Java中extends一定是代表继承吗?

    Java中extends一定是代表继承吗?

    今天小编就为大家分享一篇关于Java中extends一定是代表继承吗?,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-01-01
  • Java设计模式编程中简单工厂与抽象工厂模式的使用实例

    Java设计模式编程中简单工厂与抽象工厂模式的使用实例

    这篇文章主要介绍了Java设计模式编程中简单工厂与抽象工厂模式的使用实例,简单工厂与抽象工厂都可以归类于设计模式中的创建型模式,需要的朋友可以参考下
    2016-04-04
  • java动态规划算法——硬币找零问题实例分析

    java动态规划算法——硬币找零问题实例分析

    这篇文章主要介绍了java动态规划算法——硬币找零问题,结合实例形式分析了java动态规划算法——硬币找零问题相关原理、实现方法与操作注意事项,需要的朋友可以参考下
    2020-05-05
  • mybatis快速入门学习教程新手注意问题小结

    mybatis快速入门学习教程新手注意问题小结

    MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架。接下来通过本文给大家介绍mybatis快速入门学习教程新手注意问题小结,需要的朋友可以参考下
    2017-02-02
  • Java利用ffmpeg实现视频MP4转m3u8

    Java利用ffmpeg实现视频MP4转m3u8

    本文综合了下网上教程,从ffmpeg工具转码,ffmpeg视频播放,java语言操控ffmpeg转码,转码后视频上传阿里云oss,四个方面完整记录下这个流程,需要的朋友可以参考下
    2024-02-02

最新评论