【问题标题】:Comparator with double type双倍型比较器
【发布时间】:2020-03-24 10:15:25
【问题描述】:

我写了以下代码:

public class NewClass2 implements Comparator<Point>
{
    public int compare(Point p1, Point p2)
    {
        return (int)(p1.getY() - p2.getY());
    }
}

如果我假设有两个双数 3.2 - 3.1,那么差值应该是 0.1。但是,当我将数字转换为 int 时,差异最终为 0,这是不正确的。

因此我需要compare() 返回一个双精度值,而不是一个整数值。问题是,我的 getX 字段是双精度的。我该如何解决这个问题?

【问题讨论】:

    标签: java casting double comparator


    【解决方案1】:

    我建议你使用内置方法 Double.compare()。如果您需要一个使 double 值相等的范围,您可以先使用 chcek。

    return Double.compare(p1.getY(), p2.gety());
    

    if(Math.abs(p1.getY()-p2.getY()) < ERR) return 0;    
    return Double.compare(p1.getY(), p2.gety());
    

    使用 的问题是 NaN 在这两种情况下都会返回 false,从而导致处理可能不一致。例如NaN 被定义为不等于任何东西,甚至它本身,但是在 @suihock 和 @Martinho 的解决方案中,如果任一值为 NaN,则该方法每次都会返回 0,这意味着 NaN 等于一切。

    【讨论】:

    • Java 7 为 LongInteger 的一致性添加了 compare()。
    • 这是Double.compare()link to the source code,看看它如何处理NaN
    • 如果您希望在 NaN 上的行为略有不同,您也可以使用 Math.signum
    【解决方案2】:

    您无需返回double

    Comparator 接口用于为被比较的元素建立排序。使用double 的字段与此排序无关。

    你的代码没问题。

    对不起,我错了,再次阅读问题,这是你需要的:

    public class NewClass2 implements Comparator<Point> {
        public int compare(Point p1, Point p2) {
            if (p1.getY() < p2.getY()) return -1;
            if (p1.getY() > p2.getY()) return 1;
            return 0;
        }    
    }
    

    【讨论】:

    • 我认为 NaN*_INFINITY 会失败
    【解决方案3】:

    从 Java 1.8 开始你也可以使用

    Comparator.comparingDouble(p -> p.getY())
    

    【讨论】:

      【解决方案4】:

      方法compare 应该返回一个int。它是一个数字:

      • 小于小于零,如果第一个值小于第二个;
      • 等于为零,如果两个值相等;
      • 大于大于零,如果第一个值大于第二个;

      您不需要返回double。您必须返回一个int 来实现Comparator 接口。根据我上面概述的规则,您只需返回正确的int

      你不能简单地从 int 转换,就像你说的那样,0.1 的差异将导致 0。你可以简单地这样做:

      public int compare(Point p1, Point p2)
      {
          double delta= p1.getY() - p2.getY();
          if(delta > 0) return 1;
          if(delta < 0) return -1;
          return 0;
      }
      

      但是由于浮点值的比较总是很麻烦,所以应该在一定的范围内进行比较(见this question),如下:

      public int compare(Point p1, Point p2)
      {
          double delta = p1.getY() - p2.getY();
          if(delta > 0.00001) return 1;
          if(delta < -0.00001) return -1;
          return 0;
      }
      

      【讨论】:

      • 感谢您的完整回答!我得到了整个!我永远不会忘记这样的方式
      【解决方案5】:

      在 Java 8 中非常方便,随心所欲地选择任何人:

      Comparator<someClass> cp = (a, b) ->  Double.compare(a.getScore(), b.getScore());
      
      Comparator<someClass> cp = Comparator.comparing(someClass::getScore);
      
      Comparator<someClass> cp = Comparator.comparingDouble(someClass::getScore);
      

      【讨论】:

        【解决方案6】:

        我只是想在 JDK 8 上扩展 Peter Lawrey 的回答,如果你这样做的话:

        public class NewClass2 implements Comparator<Point> {
            public int compare(Point p1, Point p2) {
                return Double.compare(p1.getY(), p2.gety());
            }    
        }
        

        你可以很容易地使用 lambda 表达式来定义这个比较器

        (Point p1,Point p2) -> Double.compare(p1.getY(), p2.gety())  
        

        更好的是,您可以使用这样的成员引用:

        Double::compare
        

        【讨论】:

        • 我喜欢在这个答案中使用 lambda,这是一个非常好的建议。我不明白您如何使用会员参考?你能举个例子吗?谢谢
        【解决方案7】:

        Double.compare(/**double value 1*/, /**double value 2*/); 与新的 Comparator 一起用于您的模型类双精度值。

        public static List<MyModel> sortByDouble(List<MyModel> modelList) {
                Collections.sort(modelList, new Comparator<MyModel>() {
                    @Override
                    public int compare(MyModels1, MyModels2) {
                        double s1Distance = Double.parseDouble(!TextUtils.isEmpty(s1.distance) ? s1.distance : "0");
                        double s2Distance = Double.parseDouble(!TextUtils.isEmpty(s2.distance) ? s2.distance : "0");
                        return Double.compare(s1Distance, s2Distance);
                    }
                });
                return modelList;
            }
        

        【讨论】:

        • 请注意,您可以使用 Double.compare(d2, d1) 而不是 Double.compare(d1, d2) 来恢复排序顺序。明显但仍然。
        【解决方案8】:

        好吧,您可以在转换为整数之前将这些双精度值乘以适当的因子,例如。在您的情况下,因为它只有一位小数,所以 10 将是一个很好的因素;

        return (int)(p1.getY()*10 - p2.getY()*10);
        

        【讨论】:

        • 此答案仅在某些情况下有效。 IE。乘以 10 将导致双精度值变为整数。
        • @robjwilkins:您能否澄清一下这种选择适当因子的方法在哪种情况下不起作用?
        • 在 getY 返回一个不能乘以 10 得到整数的数字的情况下不起作用。例如,如果 getY 返回 3.2111,则此解决方案将不起作用。由于 getY 返回一个 double,它返回 3.2111 是完全可行的。因此,这种解决方案非常有限,而且还有很多更好的选择。
        • @robjwilkins 在你提到的“合适的因素”是 10000 而不是 10 的情况下。同意简单性伴随着限制和权衡,因此用户根据自己的需要决定最可行的方法/她的用例。
        【解决方案9】:
        Double min  = Arrays.stream(myArray).min(Double::compare).get();
        

        【讨论】:

          【解决方案10】:
          int compare(Double first, Double second) {
              if (Math.abs(first - second) < 1E-6) {
                  return 0;
              } else {
                  return Double.compare(first, second);
              }
          }
          

          【讨论】:

            猜你喜欢
            • 2011-05-15
            • 1970-01-01
            • 2015-10-11
            • 1970-01-01
            • 2010-09-20
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多