探讨:Java中删除数组中重复元素

开发 后端
我有一个数组(元素个数为0哈),希望添加进去元素不能重复。拿到这样一个问题,我可能会快速的写下代码,这里数组用ArrayList.

这个是一个老问题,但是发现大多数人说的还不够透。小弟就在这里抛砖引玉了,欢迎拍砖.......

问题:比如我有一个数组(元素个数为0哈),希望添加进去元素不能重复。

拿到这样一个问题,我可能会快速的写下代码,这里数组用ArrayList.

  1. private static void testListSet(){  
  2.         List<String> arrays = new ArrayList<String>(){  
  3.             @Override 
  4.             public boolean add(String e) {  
  5.                 for(String str:this){  
  6.                     if(str.equals(e)){  
  7.                         System.out.println("add failed !!!  duplicate element");  
  8.                         return false;  
  9.                     }else{  
  10.                         System.out.println("add successed !!!");  
  11.                     }  
  12.                 }  
  13.                 return super.add(e);  
  14.             }  
  15.         };  
  16.                 arrays.add("a");arrays.add("b");arrays.add("c");arrays.add("b");  
  17.         for(String e:arrays)  
  18.             System.out.print(e);  
  19.     } 

这里我什么都不关,只关心在数组添加元素的时候做下判断(当然添加数组元素只用add方法),是否已存在相同元素,如果数组中不存在这个元素,就添加到这个数组中,反之亦然。这样写可能简单,但是面临庞大数组时就显得笨拙:有100000元素的数组天家一个元素,难道要调用100000次equal吗?这里是个基础。

问题:加入已经有一些元素的数组了,怎么删除这个数组里重复的元素呢?

大家知道java中集合总的可以分为两大类:List与Set。List类的集合里元素要求有序但可以重复,而Set类的集合里元素要求无序但不能重复。那么这里就可以考虑利用Set这个特性把重复元素删除不就达到目的了,毕竟用系统里已有的算法要优于自己现写的算法吧。

  1. public static void removeDuplicate(List<People> list){  
  2.    HashSet<People> set = new HashSet<People>(list);  
  3.    list.clear();  
  4.    list.addAll(set);  
  5. }  
  6.  
  7. ivate static People[] ObjData = new People[]{  
  8.     new People(0"a"),new People(1"b"),new People(0"a"),new People(2"a"),new People(3"c"),  
  9. }; 
  1. public class People{  
  2.     private int id;  
  3.     private String name;  
  4.       
  5.     public People(int id,String name){  
  6.         this.id = id;  
  7.         this.name = name;  
  8.     }  
  9.       
  10.     @Override 
  11.     public String toString() {  
  12.         return ("id = "+id+" , name "+name);  
  13.     }  
  14.       

上面的代码,用了一个自定义的People类,当我添加相同的对象时候(指的是含有相同的数据内容),调用removeDuplicate方法发现这样并不能解决实际问题,仍然存在相同的对象。那么HashSet里是怎么判断像个对象是否相同的呢?打开HashSet源码可以发现:每次往里面添加数据的时候,就必须要调用add方法:

  1.       @Override 
  2.      public boolean add(E object) {  
  3.          return backingMap.put(object, this) == null;  
  4.      } 

这里的backingMap也就是HashSet维护的数据,它用了一个很巧妙的方法,把每次添加的Object当作HashMap里面的KEY,本身HashSet对象当作VALUE。这样就利用了Hashmap里的KEY***性,自然而然的HashSet的数据不会重复。但是真正的是否有重复数据,就得看HashMap里的怎么判断两个KEY是否相同。

  1.         @Override public V put(K key, V value) {  
  2. 390         if (key == null) {  
  3. 391             return putValueForNullKey(value);  
  4. 392         }  
  5. 393   
  6. 394         int hash = secondaryHash(key.hashCode());  
  7. 395         HashMapEntry<K, V>[] tab = table;  
  8. 396         int index = hash & (tab.length - 1);  
  9. 397         for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {  
  10. 398             if (e.hash == hash && key.equals(e.key)) {  
  11. 399                 preModify(e);  
  12. 400                 V oldValue = e.value;  
  13. 401                 e.value = value;  
  14. 402                 return oldValue;  
  15. 403             }  
  16. 404         }  
  17. 405   
  18. 406         // No entry for (non-null) key is present; create one  
  19. 407         modCount++;  
  20. 408         if (size++ > threshold) {  
  21. 409             tab = doubleCapacity();  
  22. 410             index = hash & (tab.length - 1);  
  23. 411         }  
  24. 412         addNewEntry(key, value, hash, index);  
  25. 413         return null;  
  26. 414     } 

总的来说,这里实现的思路是:遍历hashmap里的元素,如果元素的hashcode相等(事实上还要对hashcode做一次处理),然后去判断KEY的eqaul方法。如果这两个条件满足,那么就是不同元素。那这里如果数组里的元素类型是自定义的话,要利用Set的机制,那就得自己实现equal与hashmap(这里hashmap算法就不详细介绍了,我也就理解一点)方法了:

  1. public class People{  
  2.     private int id; //  
  3.     private String name;  
  4.       
  5.     public People(int id,String name){  
  6.         this.id = id;  
  7.         this.name = name;  
  8.     }  
  9.       
  10.     @Override 
  11.     public String toString() {  
  12.         return ("id = "+id+" , name "+name);  
  13.     }  
  14.      
  15.     public int getId() {  
  16.         return id;  
  17.     }  
  18.  
  19.     public void setId(int id) {  
  20.         this.id = id;  
  21.     }  
  22.  
  23.     public String getName() {  
  24.         return name;  
  25.     }  
  26.  
  27.     public void setName(String name) {  
  28.         this.name = name;  
  29.     }  
  30.  
  31.     @Override 
  32.     public boolean equals(Object obj) {  
  33.         if(!(obj instanceof People))  
  34.             return false;  
  35.         People o = (People)obj;  
  36.         if(id == o.getId()&&name.equals(o.getName()))  
  37.             return true;  
  38.         else 
  39.             return false;  
  40.     }  
  41.       
  42.     @Override 
  43.     public int hashCode() {  
  44.         // TODO Auto-generated method stub  
  45.         return id;  
  46.         //return super.hashCode();  
  47.     }  

这里在调用removeDuplicate(list)方法就不会出现两个相同的people了。

原文链接:http://www.cnblogs.com/slider/archive/2012/01/12/2320313.html

【编辑推荐】

  1. 调查显示Java应用服务器市场 开源完胜
  2. 一个Java程序员对2011年的回顾
  3. 用Java GUI编写的画板程序
  4. Java的动态绑定机制
  5. JavaFX 2012:彻底开源
责任编辑:林师授 来源: slider的博客
相关推荐

2009-11-25 16:36:29

PHP删除数组重复元素

2009-11-25 16:29:08

PHP删除数组元素

2015-08-04 09:18:26

JavaArrayList元素

2009-09-23 09:09:22

C#删除数组重复项

2009-11-24 18:28:44

PHP函数array_

2009-11-30 18:21:21

PHP删除数组元素

2009-11-25 16:40:55

PHP函数array_

2009-11-25 15:50:53

PHP删除数组空白元素

2020-10-15 12:30:37

Python编程语言

2011-05-24 10:54:15

数据库重复数据删除

2012-05-29 15:29:14

JavaArrayList

2021-11-30 10:00:01

SQL数据重复

2021-01-14 08:23:15

LeetCode变量

2019-12-10 10:31:30

javascriptWeb前端开发

2010-09-01 16:47:18

SQL删除

2009-11-26 16:49:27

PHP删除数据库表

2023-11-23 13:43:24

Python列表

2021-06-22 10:24:22

Statement接口修改数据删除数据

2013-03-06 09:41:29

2011-07-04 17:09:54

点赞
收藏

51CTO技术栈公众号