一、前言
jdk对于大部分类(ArrayList、HashSet、Vector、ConcurrentLinkedQueue)集实现判断contains方法,都是遍历类集对象进行比较是否相等(equals值是否相等),源码分析如下:
ArrayList源码:
HashSet源码:
Vector源码:
ConcurrentLinkedQueue源码:
所以只要定义对象唯一性属性,然后重写父类Object的equals方法中判断唯一性属性就可以了,如下定义obj类,并定义属性a、b值都相等时对象才认为值相等,代码如下:
class obj implements Comparable<obj>{@b@ @b@ private String a;@b@ private String b;@b@ @b@ public obj() {@b@ super();@b@ }@b@ @b@ public obj(String a, String b) {@b@ super();@b@ this.a = a;@b@ this.b = b;@b@ }@b@ public String getA() {@b@ return a;@b@ }@b@ public String getB() {@b@ return b;@b@ }@b@ public void setA(String a) {@b@ this.a = a;@b@ }@b@ public void setB(String b) {@b@ this.b = b;@b@ }@b@ @Override@b@ public int compareTo(obj o) {@b@ // TODO Auto-generated method stub@b@ return 0;@b@ }@b@ @Override@b@ public boolean equals(Object o) {@b@ // TODO Auto-generated method stub@b@ obj _this=(obj)o;@b@ if(_this==null)@b@ return false;@b@ if(!this.getA().equals(_this.getA()))@b@ return false;@b@ if(!this.getB().equals(_this.getB()))@b@ return false;@b@ return true;@b@ }@b@ @b@}
但是有少部分实现的类集 contains方法是没有办法判断是否包含该对象的,如TreeSet
二、对比测试
下面代码对ArrayList、HashSet、Vector、ConcurrentLinkedQueue测试对比,示例代码如下:
import java.util.ArrayList;@b@import java.util.HashSet;@b@import java.util.List;@b@import java.util.Queue;@b@import java.util.TreeSet;@b@import java.util.Vector;@b@import java.util.concurrent.ConcurrentLinkedQueue;@b@@b@/**@b@ * 类描述@b@ * @author nijun@b@ * @version 版本创建于 2015-7-20@b@ */@b@@b@public class ContainsSetTest {@b@ @b@ public TreeSet<obj> treeSet=new TreeSet<obj>();@b@ public List<obj> arrayList=new ArrayList<obj>();@b@ public HashSet<obj> hashSet=new HashSet<obj>();@b@ public Vector<obj> vector=new Vector<obj>();@b@ public Queue<obj> queue=new ConcurrentLinkedQueue<obj>();@b@ @b@ @b@ public static void main(String[] args) {@b@ @b@ /**TreeSet contains Test*/@b@ ContainsSetTest test=new ContainsSetTest();@b@ obj o1=new obj("11","111");@b@ obj o2=new obj("22","222");@b@ test.treeSet.add(o1);@b@ if(!test.treeSet.contains(o2))@b@ test.treeSet.add(o2);@b@ System.out.println("TreeSet.contains()->size:"+test.treeSet.size());@b@ @b@ /**ArrayList contains Test*/@b@ test.arrayList.add(o1);@b@ if(!test.arrayList.contains(o2))@b@ test.arrayList.add(o2);@b@ System.out.println("ArrayList.contains()->size:"+test.arrayList.size());@b@ @b@ @b@ /**HashSet contains Test*/@b@ test.hashSet.add(o1);@b@ if(!test.hashSet.contains(o2))@b@ test.hashSet.add(o2);@b@ System.out.println("HashSet.contains()->size:"+test.hashSet.size());@b@ @b@ @b@ /**Vector contains Test*/@b@ test.vector.add(o1);@b@ if(!test.vector.contains(o2))@b@ test.vector.add(o2);@b@ System.out.println("Vector.contains()->size:"+test.vector.size());@b@ @b@ @b@ /**ConcurrentLinkedQueue contains Test*/@b@ test.queue.add(o1);@b@ if(!test.queue.contains(o2))@b@ test.queue.add(o2);@b@ System.out.println("ConcurrentLinkedQueue.contains()->size:"+test.queue.size());@b@ @b@ } @b@}
运行结果
TreeSet.contains()->size:1@b@ArrayList.contains()->size:2@b@HashSet.contains()->size:2@b@Vector.contains()->size:2@b@ConcurrentLinkedQueue.contains()->size:2
三、对比分析
TreeSet是只能存大小不一样的对象,如大小一样则只能保留最开始的那个对象,其实基于TreeMap进行存储实现,源码对照分析
打开NavigableMap接口实现类在TreeMap匿名类NavigableSubMap中,其containsKey方法如下(对于判断在范围的情况下,再通过TreeMap的containsKey去找)
TreeMap的containsKey方法,直接判断获取实体对象是否为空,不为空及存在这样的对象
TreeMap的getEntry方法还是最终比较对象大小,如果一样,就直接拿值相等的对象,否则拿前一个或者后一个
因此,Comparable的compareTo方法必须重新,修改类obj的compareTo方法如下:
@Override@b@ public int compareTo(obj o) {@b@ // TODO Auto-generated method stub@b@ return o.getA().compareTo(this.getA());@b@ }
再运行结果,就正常了
TreeSet.contains()->size:2
三、总结
因此对于TreeSet只能保存大小不一样的对象集合,必须重写compareTo方法以定义对象之间大小,如果实际对象没有大小,将不能存储下来,其他大部分类集(ArrayList、HashSet、Vector、ConcurrentLinkedQueue等)可以不考虑大小