zoukankan      html  css  js  c++  java
  • compareTo的实现策略

    1.compareTo用于TreeSet,而TreeSet个人认为最好用于读DB的结果集,将来可以基于compareTo的排序结果取subSet。写DB的时候,可以使用HashSet而不是TreeSet,因为写之前的结构不需要考虑排序与取子集。

    2.compareTo如何实现:按照想要比较的字段的冲突出现的概率依次判断。
    假设表的结构:memberid, locationid,type 并且memberid,locatonid是组合主键。这样一个memberid可以对应多条locationid的记录。
    如果从DB中读出某个member的所有记录放到TreeSet,并且将来根据type排序,那么type需要第一个出现在compareTo里面,同时只有type,其它相同type的记录可能就添加不到treeset里,所以还需要拉上一个类似于identify的字段,当然就是locationid。
    这样想要比较的字段就是type,locationid,根据冲突出现的可能性,当然是先type,后locationid。

    示例: MemberLocationElement对象放到TreeSet中的compareTo的实现策略:先判断最可能相同的type值,然后再判断最不可能冲突的locationid。TreeSet主要用于读从DB读出结果集时使用。在写入的时候,需要保证locationid不同,可以使用HashSet来写。所以,TreeSet个人觉得最好的方式是读的时候使用。而不是希望它做add的操作。

        public static class MemberLocationElementComparator implements Comparator<MemberLocationElement>,Serializable{
            private static final long serialVersionUID = 1L;
    
            @Override
            public int compare(MemberLocationElement o1, MemberLocationElement o2)
            {
                if (o1 == null || o2 == null)
                    return -1;
                if (o1.getType().getVal() == o2.getType().getVal())
                {
                    return o1.getLocationid() - o2.getLocationid();
                }
                return o1.getType().getVal() - o2.getType().getVal();
            }
        }

    又比如从DB读Person记录到TreeSet,Person包含fn以及ln二个属性分别表示first_name,last_name.  假设fn+ln构造复合主键。如果要读所有的用户记录到TreeSet
    此时compareTo的字段应该是fn,ln,注意这里的ln并不是一个identify的字段,但是由于fn+ln是identify,按照冲突出现的概率,fn冲突的可能性更大,所以先比较。
    比如加入李想,李晨, 不能因为加入李想就由于first_name=李而不让加入李晨,所以如果fn相等,可以接着比较ln。
    对于不同的fn,当然可以加入到TreeSet,但是对于相同的fn,此时就需要接着比较last_name以防止不能加入。



    又比如图片类PhotoInfo包含了blessed和uploaddate的值,blessed的值从0~7,如果实现一个2>1>6的排序,相同情况下再按uploaddate排序(最近的先显示)

    比较器实现如下:

    public static class TestComparator implements Comparator<PhotoInfo>, Serializable
        {
            private static final long serialVersionUID = 1L;
            public  static final Map<Integer, Integer> blessedIndMap       = new HashMap<Integer, Integer>();
            static
            {
                blessedIndMap.put(UserImage.S_BLESSED_GEO_PARENT,3);
                blessedIndMap.put(UserImage.S_BLESSED_GEO_ONLY,2);
                blessedIndMap.put(UserImage.S_BLESSED_PROPERTY_ONLY,1);
            }
    
            @Override
            public int compare(PhotoInfo o1, PhotoInfo o2)
            {
                if (o1 == null || o2 == null)
                {
                    return -1;
                }
                int bind1 = getIndexByBlessed(o1.getBlessed());
                int bind2 = getIndexByBlessed(o2.getBlessed());
                if (bind1 == bind2)
                {
                    //recently first show,因为默认都是升序,所以取负值。
                    return -(o1.getUploadedDate().compareTo(o2.getUploadedDate()));
                }
                //blessed show order 2,1,6,other,因为默认都是升序,所以取负值。
                return -(bind1 - bind2);
            }
            
            public int getIndexByBlessed(int blessed)
            {
                return blessedIndMap.get(blessed) == null ? 0 : blessedIndMap.get(blessed);
            }
        }

    对于List,使用比较器如下:Collections.sort(photoInfoList, new TestComparator());

    3.特别强调Map通过comparator只能比较value,如果想让key也排序或者是做到有序Map,就只能使用LinkedHashMap,它支持按照添加的顺序排序。

    4.TreeSet的接口划分及使用:
    对于remove, removeAll这样的操作依赖于Element定义的equal方法。

    对于add,addAll,headSet, tailSet,subSet这样操作依赖于compareTo方法。

    取某个范围的结果集使用tailSet+headSet。subSet取的是半开半闭区间的结果集,不好操作。tailSet表示>=   headSet表示<

    TreeSet是实现类,根据排序取范围的操作都定义在接口SortedSet中,建议使用SortedSet而不是具体类。

    import java.util.Comparator;
    import java.util.HashSet;
    import java.util.Set;
    import java.util.TreeSet;
    
    public class TreeSetTest {
    
        /**
         * @param args
         */
       
        public enum Type{
            GOING(1),BEEN(2),GOING_THEN_BEEN(3);
            private int val;
            private Type(int val){
                this.val=val;
            }
            public int getVal() {
                return val;
            }
            public void setVal(int val) {
                this.val = val;
            }
        }
        public static class Element{
            private int memeberid;
            private int locationid;
            private Type type;
            public Element(){}
            public int getMemeberid() {
                return memeberid;
            }
            public void setMemeberid(int memeberid) {
                this.memeberid = memeberid;
            }
            public int getLocationid() {
                return locationid;
            }
            public void setLocationid(int locationid) {
                this.locationid = locationid;
            }
            public Type getType() {
                return type;
            }
            public void setType(Type type) {
                this.type = type;
            }
            public Element(int memeberid, int locationid, Type type) {
                super();
                this.memeberid = memeberid;
                this.locationid = locationid;
                this.type = type;
            }
            @Override
            public int hashCode() {
                final int prime = 31;
                int result = 1;
                result = prime * result + locationid;
                result = prime * result + memeberid;
                return result;
            }
            @Override
            public boolean equals(Object obj) {
                if (this == obj)
                    return true;
                if (obj == null)
                    return false;
                if (getClass() != obj.getClass())
                    return false;
                Element other = (Element) obj;
                if (locationid != other.locationid)
                    return false;
                if (memeberid != other.memeberid)
                    return false;
                return true;
            }
           
        }
        public static void main(String[] args) {
            TreeSet<Element> elements=new TreeSet<Element>(new Comparator<Element>() {
               
                @Override
                public int compare(Element o1, Element o2) {
                    if(o1.getType().getVal()==o2.getType().getVal()){
                        return o1.getLocationid()-o2.getLocationid();
                    }
                    return o1.getType().getVal()-o2.getType().getVal();
                }
            });
            Element e1=new Element(111111, 294211, Type.GOING);
            Element e2=new Element(111111, 294212, Type.BEEN);
            Element e3=new Element(111111, 294213, Type.BEEN);
            Element e4=new Element(111111, 294214, Type.GOING_THEN_BEEN);
           
            elements.add(e1);
            elements.add(e2);
            elements.add(e3);
            elements.add(e4);
            
            
            loadSet(elements);
            
            System.out.println("-----------------------");
            Element from=new Element();
            from.setType(Type.GOING);
           
            Element to=new Element();
            to.setType(Type.GOING_THEN_BEEN);
           
            Element too=new Element();
            too.setType(Type.BEEN);
           
            Set<Element> subSet=elements.tailSet(too).headSet(to);
    //      Set<Element> subSet=elements.tailSet(to);
    //      Set<Element> subSet=elements.tailSet(too);
    //      Set<Element> subSet=elements.subSet(from,Boolean.FALSE, to,Boolean.FALSE);
            
            loadSet(subSet);
    
            System.out.println("-------------------------");
            
            HashSet<Element> rmset=new HashSet<Element>();
            e2.setType(Type.GOING_THEN_BEEN);
            rmset.add(e2);
            e3.setType(Type.GOING_THEN_BEEN);
            rmset.add(e3);
            //其实是逐个调用remove方法,remove方法的根据是 如果此 set 中包含满足 (o==null ? e==null : o.equals(e)) 的元素 e,则移除它。可以看到remove这样不涉及到排序的操作equal是起作用的。
            elements.removeAll(rmset);
            elements.addAll(rmset);
            loadSet(elements);
        }
        private static void loadSet(Set<Element> set)
        {
            for (Element element : set) {
                System.out.println(element.locationid+"|"+element.getType().name());
            }
        }
    
    }
     
  • 相关阅读:
    Docker 部署net5程序
    如何将Docker升级到最新版本
    IntelliJ IDEA修改maven默认仓库地址
    PowerDesigner 导出表结构 到Excel
    gradle加载项目过慢
    linux安装docker配置阿里云镜像
    svn 新建文件不能直接提交终于解决了
    Vs2017 NPM 安装 部署
    MYSQL日期时间字符串互转
    消除svn选定(checkout)桌面上文件显示一大堆问号。
  • 原文地址:https://www.cnblogs.com/highriver/p/2757183.html
Copyright © 2011-2022 走看看