Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/378.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过多个字段对JavaBean进行排序的正确方法_Java_Sorting_Comparator - Fatal编程技术网

通过多个字段对JavaBean进行排序的正确方法

通过多个字段对JavaBean进行排序的正确方法,java,sorting,comparator,Java,Sorting,Comparator,我们的代码带有复杂的比较器,用于在整个应用程序中对java对象进行排序。从历史上看,这些方法都是有效的,但是自从在Java7中引入TimSort之后,我们偶尔会发现比较方法违反了它的一般约定错误。。取决于对象中保存的数据 下面是我们的一个遗留比较工具的示例(可能已经有十年历史了——请原谅这种不可靠的做法): 所以,我想复制这个功能,但是使用一个比较器,可以安全地与TimSort一起使用 从代码中可以看出,此比较有多个级别 它将比较组码 如果组码相同,则会比较排序顺序 如果排序顺序相同,它将比较描

我们的代码带有复杂的比较器,用于在整个应用程序中对java对象进行排序。从历史上看,这些方法都是有效的,但是自从在Java7中引入TimSort之后,我们偶尔会发现比较方法违反了它的一般约定错误。。取决于对象中保存的数据

下面是我们的一个遗留比较工具的示例(可能已经有十年历史了——请原谅这种不可靠的做法):

所以,我想复制这个功能,但是使用一个比较器,可以安全地与TimSort一起使用

从代码中可以看出,此比较有多个级别

  • 它将比较组码
  • 如果组码相同,则会比较排序顺序
  • 如果排序顺序相同,它将比较描述
  • 这意味着它将返回特定级别的比较结果。这可能是两个字符串或两个整数的比较结果。我认为这就是打破传统的原因

    我能够使这个比较器解决一般合同问题的唯一方法是对bean的内容进行散列并执行字符串比较。其他想法包括编写我们自己的排序函数。。肯定有更好的办法吗


    bean是否应该以另一种方式构造以支持这一点?

    上述
    比较器的主要问题是它不是可传递的。它似乎在较旧的JDK上“起作用”,因为它们没有提供对损坏的比较器的检测,但它在一般情况下无法正常工作,直到JDK 7才发现错误行为

    它的非传递性来源于
    groupCode
    属性上的条件比较。 考虑当比较器将对象A和B作为 > SoTrOrth< /COD>字段省略比较<代码>组代码< /代码>,因为<代码>“函数”。 由于
    sortOrder
    ,对象B和C按BgroupCode
    比较,直接比较A和C时,A和C可能被排序为C比较器的传递性要求

    要解决此问题,应始终考虑
    groupCode
    ,并且由于
    refRltshpTypeCode
    值而跳过
    groupCode
    的每个对象都应被视为小于任何现在使用
    groupCode
    进行比较的对象

    比较方法应该是这样的(这只是给你一个想法):

    在哪里

    来自@RomanKonovai的消息是正确的,但是添加了更多细节

    考虑代码如何比较这三个对象,并假设所有非引用:

                   A          B          C
    Status         UNATTACHED UNATTACHED UNATTACHED
    RefRltshpType  CUSTOM     FUNCTION   CUSTOM
    Group          Cat        Ball       Apple
    SortOrder      10         20         30
    
    通过问题中的实现,我们可以看到AA,或者
    A
    。这显然是不符合逻辑的,因为排序顺序取决于
    状态
    RefRltshpType
    的值,由
    排序器
    决定,这两者之间没有任何联系。本质上,这意味着排序顺序未定义,因为结果完全取决于输入的顺序,即
    sort(sort(List))
    可能不会给出与
    sort(List)
    相同的结果

    解决此问题的方法是执行以下操作:

    private int objectCompare(String allowed, Comparable v1, Comparable v2) {
      if (v1 == v2) return 0;
      if (v1 == null) return 1;
      if (v2 == null) return -1;
      boolean c1 = v1.equals(allowed);
      boolean c2 = v2.equals(allowed);
      return c1 ? c2 ? 0 : 1 : c2 ? -1 : 0;
    }
    private int objectCompare(Comparable v1, Comparable v2) {
      if (v1 == v2) return 0;
      if (v1 == null) return 1;
      if (v2 == null) return -1;
      return v1.compare(v2);
    }
    public int compare(TemplateBean b1, TemplateBean b2) {
    
      // avoid null pointer exceptions
      if (b1 == b2) return 0;
      if (b1 == null) return 1;
      if (b2 == null) return -1;
    
      int cmp = objectCompare("UNATTACHED", b1.getStatusCode(), b2.getStatusCode());
      if (cmp == 0) {
        cmp = objectCompare("FIELDSIMPLE", b1.getRefRltshpTypeCode(), b2.getRefRltshpTypeCode());
        if (cmp == 0) {
          cmp = objectCompare("CUSTOM", b1.getRefRltshpTypeCode(), b2.getRefRltshpTypeCode());
          if (cmp == 0) {
            cmp = objectCompare("FUNCTION", b1.getRefRltshpTypeCode(), b2.getRefRltshpTypeCode());
            if (cmp == 0) {
              cmp = objectCompare(b1.getGroupCode(), b2.getGroupCode());
              if (cmp == 0) {
                cmp = objectCompare(b1.getSortOrder(), b2.getSortOrder());
                if (cmp == 0) {
                  cmp = objectCompare(b1.getShortDescription(), b2.getShortDescription());
                }
              }
            }
          }
        }
      }
    
      return cmp;
    }
    

    我对TimSort不太熟悉,但有一件事可能会对您有所帮助,那就是为要比较的字段实现某种枚举,而不是尝试执行复杂的字符串比较操作。我不确定这是否是一个解决这个问题的好方法,但这是我的一个想法。这里有太多的字符串比较。你真的应该把字符串转换成相应的数字或其他东西,并对它们进行比较,而不是试图去挖掘这些混乱的条件。我认为问题不在于如何确定比较(使用字符串或枚举),我认为这更多地与TimSort有这个限制的事实有关:实现者还必须确保关系是可传递的:((compare(x,y)>0)和&(compare(y,z)>0))意味着compare(x,z)>0。这意味着,如果X和Y在同一级别进行比较,但Y和Z在不同级别进行比较,则返回的整数可能会违反此规则。我需要返回一个表示顺序的值,但也不违反X>Y>Z规则。乍一看,问题出在第三个
    if
    (不包括空检查)中的某个地方。最后两个似乎没有问题,因为它们使用字符串和整数比较,而这些比较已经是可传递的。等我有更多的时间,我会仔细看的。谢谢你的解释。
    private static boolean shouldBeComparenByGroupCode(TemplateBean b1) {
         return !"UNATTACHED".equals(b1.getStatusCode()) &&
                !"FIELDSIMPLE".equals(b1.getRefRltshpTypeCode()) &&
                !"CUSTOM".equals(b1.getRefRltshpTypeCode()) &&
                !"FUNCTION".equals(b1.getRefRltshpTypeCode());
    }
    
                   A          B          C
    Status         UNATTACHED UNATTACHED UNATTACHED
    RefRltshpType  CUSTOM     FUNCTION   CUSTOM
    Group          Cat        Ball       Apple
    SortOrder      10         20         30
    
    private int objectCompare(String allowed, Comparable v1, Comparable v2) {
      if (v1 == v2) return 0;
      if (v1 == null) return 1;
      if (v2 == null) return -1;
      boolean c1 = v1.equals(allowed);
      boolean c2 = v2.equals(allowed);
      return c1 ? c2 ? 0 : 1 : c2 ? -1 : 0;
    }
    private int objectCompare(Comparable v1, Comparable v2) {
      if (v1 == v2) return 0;
      if (v1 == null) return 1;
      if (v2 == null) return -1;
      return v1.compare(v2);
    }
    public int compare(TemplateBean b1, TemplateBean b2) {
    
      // avoid null pointer exceptions
      if (b1 == b2) return 0;
      if (b1 == null) return 1;
      if (b2 == null) return -1;
    
      int cmp = objectCompare("UNATTACHED", b1.getStatusCode(), b2.getStatusCode());
      if (cmp == 0) {
        cmp = objectCompare("FIELDSIMPLE", b1.getRefRltshpTypeCode(), b2.getRefRltshpTypeCode());
        if (cmp == 0) {
          cmp = objectCompare("CUSTOM", b1.getRefRltshpTypeCode(), b2.getRefRltshpTypeCode());
          if (cmp == 0) {
            cmp = objectCompare("FUNCTION", b1.getRefRltshpTypeCode(), b2.getRefRltshpTypeCode());
            if (cmp == 0) {
              cmp = objectCompare(b1.getGroupCode(), b2.getGroupCode());
              if (cmp == 0) {
                cmp = objectCompare(b1.getSortOrder(), b2.getSortOrder());
                if (cmp == 0) {
                  cmp = objectCompare(b1.getShortDescription(), b2.getShortDescription());
                }
              }
            }
          }
        }
      }
    
      return cmp;
    }