【问题标题】:Order arraylist based on multiple connection基于多连接排序arraylist
【发布时间】:2016-02-17 09:10:19
【问题描述】:

这是我的画外音

public class SomeVO {

    private String name;        
    private String usageCount;
    private String numberofReturns;
    private String trendNumber;
    private String nonTrendNumber;
    private String trendType;
    private String auditType;
    public SomeVO(String name,String usageCount,String numberofReturns,String trendNumber,String nonTrendNumber,String trendType,String auditType){
        this.name = name;
        this.usageCount = usageCount;
        this.numberofReturns = numberofReturns;
        this.trendNumber = trendNumber;
        this.nonTrendNumber = nonTrendNumber;
        this.trendType = trendType;
        this.auditType = auditType;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getUsageCount() {
        return usageCount;
    }
    public void setUsageCount(String usageCount) {
        this.usageCount = usageCount;
    }
    public String getNumberofReturns() {
        return numberofReturns;
    }
    public void setNumberofReturns(String numberofReturns) {
        this.numberofReturns = numberofReturns;
    }
    public String getTrendNumber() {
        return trendNumber;
    }
    public void setTrendNumber(String trendNumber) {
        this.trendNumber = trendNumber;
    }
    public String getNonTrendNumber() {
        return nonTrendNumber;
    }
    public void setNonTrendNumber(String nonTrendNumber) {
        this.nonTrendNumber = nonTrendNumber;
    }
    public String getTrendType() {
        return trendType;
    }
    public void setTrendType(String trendType) {
        this.trendType = trendType;
    }
    public String getAuditType() {
        return auditType;
    }
    public void setAuditType(String auditType) {
        this.auditType = auditType;
    }
}

这是我的价值观

List<SomeVO> myList = new ArrayList<SomeVO>();
        SomeVO some = new SomeVO("A","0","0","123","123","Trend","AuditX");
        myList.add(some);
        some = new SomeVO("B","1","1","234","234","Non trend","AuditX");
        myList.add(some);
        some = new SomeVO("C","0","2","345","345","Trend","AuditX");
        myList.add(some);
        some = new SomeVO("D","2","3","546","546","Trend","AuditX");
        myList.add(some);
        some = new SomeVO("E","2","4","678","678","Non trend","AuditX");
        myList.add(some);
        some = new SomeVO("F","0","0","123","123","Non trend","AuditA");
        myList.add(some);
        some = new SomeVO("G","0","0","123","123","Trend","AuditB");
        myList.add(some);

这是我的比较器

public String currentAudit = "AuditX";
public class AuditComparator implements Comparator<SomeVO> {

        @Override
        public int compare(SomeVO o1, SomeVO o2) {
            if(currentAudit.equalsIgnoreCase(o1.getAuditType()) && currentAudit.equalsIgnoreCase(o2.getAuditType())) {
                int value1 = o2.getUsageCount().compareTo(o1.getUsageCount());
                if (value1 == 0) {
                    int value2 = o1.getNumberofReturns().compareTo(o2.getNumberofReturns());
                    if(o1.getTrendType().equalsIgnoreCase("Trend") && o2.getTrendType().equalsIgnoreCase("Trend")) {
                        if (value2 == 0) {
                            return o1.getTrendNumber().compareTo(o2.getTrendNumber());
                        } else {
                            return value2;
                        }
                    } else {
                        if (value2 == 0) {
                            return o1.getNonTrendNumber().compareTo(o2.getNonTrendNumber());
                        } else {
                            return value2;
                        }
                    }
                }
                return value1;
            } else {
                return 1;
            }

        }
    }

我正在尝试根据以下条件对 VO 进行排序

  1. 应将 currentAudit 的第一组值纳入 考虑,即 AuditX

    a) 那么它应该被排序 使用次数按降序排列

    b) 如果发现相同的使用次数,那么它 应按返回计数升序排序

    c) 如果相同 返回计数然后它应该检查趋势类型,如果趋势类型 ="Trend" 那么它应该使用趋势编号排序,否则使用非趋势编号。

  2. 那么它应该考虑其余所有的 auditType 并排序 a),b),c) 条件类似于 currentAudit。我试着实现它,我 最后只有上面的比较器。预期结果:D、A、C、E、 F,G。但我得到 G,F,D,E,B,A,C。请帮我更新 上面的比较器。

【问题讨论】:

  • 第一个猜测:您将数字作为字符串进行比较,我建议将这些字符串转换为数字。以任何方式测试七个列表项:调试(使用断点)并查看比较器“失败”的位置应该不难。
  • 乍一看你的期望是错误的 D,然后 E 是正确的排序
  • A.auditTypeB.auditType 都等于"AuditX" 时,则compare(A, B) == compare(B, A) == 1。这违反了比较器的规则。
  • if(currentAudit.equalsIgnoreCase(o1.getAuditType())) 中有一些奇怪的地方:你在比较 o1 但你没有检查 o2。
  • @Sercan Ozdemir,这里的条件首先是趋势,然后是审计 X 的非趋势,所以 D、A、C、E、F、G。

标签: java sorting arraylist collections


【解决方案1】:

您的比较器不满足一个简单的条件:它不是无状态的。以下内容应始终为真:A&gt;B =&gt; B&lt;A。在您的情况下,在某些情况下A&gt;B and B&gt;A

【讨论】:

    【解决方案2】:

    我通过根据 AuditX 将实际列表拆分为 2 个列表并在另一个列表中休息来解决它。然后在比较器下面一一使用,然后合并到一个结果列表中。效果很好。

    for(SomeVO some:myList) {
                if(some.getAuditType().equalsIgnoreCase("AuditX")) {
                    auditX.add(some);
                } else {
                    auditY.add(some);
                }
            }
            Collections.sort(auditX, new AuditComparator());            
            Collections.sort(auditY, new AuditComparator());
    
        public class AuditComparator implements Comparator<SomeVO> {
    
                @Override
                public int compare(SomeVO o1, SomeVO o2) {
                    int value1 = o2.getUsageCount().compareTo(o1.getUsageCount());
                     if (value1 == 0) {
                            int value2 = o1.getNumberofReturns().compareTo(o2.getNumberofReturns());
                            if (value2 == 0) {
                                return (o1.getTrendType().equalsIgnoreCase("Trend") && o2.getTrendType().equalsIgnoreCase("Trend")) ?
                                        o1.getTrendNumber().compareTo(o2.getTrendNumber()):o1.getNonTrendNumber().compareTo(o2.getNonTrendNumber());
                            } else {
                                return value2;
                            }            
                }
                    return value1;
            }
    

    【讨论】:

      【解决方案3】:

      比较器底部的 return 1 会产生错误。 如果第二个元素大于第一个元素,比较器只会返回 1,但如果它们不同,则始终返回 1,因此第一个排序标准会很混乱。

         // a helper for case insensitive comparison
         private int compareIgnoreCase(String o1,String o2) {
             return o1.toLowercase.compareTo(o2.toLowercase());
         }
      
         @Override
          public int compare(SomeVO o1, SomeVO o2) {
              int result=compareIgnoreCase(o1.getAuditType(),o2.getAuditType());
              if (result==0) {
                  // we need to go to the 2nd criteria
                  result=o2.getUsageCount().compareTo(o1.getUsageCount());
              }
              if (result==0) {
                  // ok, 1st and 2nd criteria was the same, go to the 3rd             
                result=o1.getNumberofReturns().compareTo(o2.getNumberofReturns());
              }
              if (result==0) {
                  // check trends
                  ...
              }
              return result;
          }
      

      我发现多重比较标准的这种表示使代码更容易理解。我们首先进行最高优先级的比较,如果之前的比较返回两个元素相同(即结果仍然为零),则继续进行进一步的比较。

      如果您需要在某个级别进行降序排序,只需输入 -,例如:

       结果=-o1.something.compareTo(o2.something) 

      在一个方法中只有一个退出点是个好主意(这也便于跟踪正在发生的事情)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-12-08
        • 2015-10-06
        • 1970-01-01
        • 1970-01-01
        • 2014-03-06
        • 2017-09-17
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多