Java 向比较器的比较方法添加其他规则

Java 向比较器的比较方法添加其他规则,java,android,comparator,Java,Android,Comparator,我目前有一个代码段,它以升序返回列表的字符串: Collections.sort(myList, new Comparator<MyClass>() { @Override public int compare(MyClass o1, MyClass o2) { return o1.aString.compareTo(o2.aString); } }); 是否可以像这样使用比较器自定义列表排序?是的,这是可能的,您可以完全控制compareT

我目前有一个代码段,它以升序返回列表的字符串:

Collections.sort(myList, new Comparator<MyClass>() {
    @Override
    public int compare(MyClass o1, MyClass o2) {
        return o1.aString.compareTo(o2.aString);
    }
});

是否可以像这样使用
比较器自定义列表排序?

是的,这是可能的,您可以完全控制compareTo()方法。两件事:

  • 使用字符串#equals而不是==来比较字符串
  • 确保选中这两个参数以比较您的异常情况
  • 一种具体的实现方式,其中一些词总是第一个,一些词总是最后一个,在例外情况中定义了顺序:

    Map<String, Integer> exceptionMap = new HashMap<>();
    exceptionMap.put("lowest", -2);
    exceptionMap.put("second_lowest", -1);
    exceptionMap.put("second_highest", 1);
    exceptionMap.put("highest", 2);
    
    public int compareToWithExceptionMap(String s1, String s2) {
      int firstExceptional = exceptionMap.getOrDefault(s1, 0);
      int secondExceptional = exceptionMap.getOrDefault(s2, 0);
    
      if (firstExceptional == 0 && secondExceptional == 0) {
        return s1.compareTo(s2);
      }
      return firstExceptional - secondExceptional;
    }
    
    Map exceptionMap=newhashmap();
    例外的MAP.put(“最低”为-2);
    例外地图放置(“第二低”,1);
    例外地图放置(“第二高”,1);
    例外地图放置(“最高”,2);
    public int compareToWithExceptionMap(字符串s1、字符串s2){
    int firstException=exceptionMap.getOrDefault(s1,0);
    int secondException=exceptionMap.getOrDefault(s2,0);
    如果(第一异常==0&&SecondException==0){
    返回s1.compareTo(s2);
    }
    返回第一个例外-第二个例外;
    }
    
    是的,这是可能的,您可以完全控制compareTo()方法。两件事:

  • 使用字符串#equals而不是==来比较字符串
  • 确保选中这两个参数以比较您的异常情况
  • 一种具体的实现方式,其中一些词总是第一个,一些词总是最后一个,在例外情况中定义了顺序:

    Map<String, Integer> exceptionMap = new HashMap<>();
    exceptionMap.put("lowest", -2);
    exceptionMap.put("second_lowest", -1);
    exceptionMap.put("second_highest", 1);
    exceptionMap.put("highest", 2);
    
    public int compareToWithExceptionMap(String s1, String s2) {
      int firstExceptional = exceptionMap.getOrDefault(s1, 0);
      int secondExceptional = exceptionMap.getOrDefault(s2, 0);
    
      if (firstExceptional == 0 && secondExceptional == 0) {
        return s1.compareTo(s2);
      }
      return firstExceptional - secondExceptional;
    }
    
    Map exceptionMap=newhashmap();
    例外的MAP.put(“最低”为-2);
    例外地图放置(“第二低”,1);
    例外地图放置(“第二高”,1);
    例外地图放置(“最高”,2);
    public int compareToWithExceptionMap(字符串s1、字符串s2){
    int firstException=exceptionMap.getOrDefault(s1,0);
    int secondException=exceptionMap.getOrDefault(s2,0);
    如果(第一异常==0&&SecondException==0){
    返回s1.compareTo(s2);
    }
    返回第一个例外-第二个例外;
    }
    
    这是可能的

    使用Java8特性 您可以将函数传递给
    比较器。comparing
    方法来定义规则。请注意,我们只返回整数,即应排在第一位的元素的最低整数

    Comparator<MyClass> myRules = Comparator.comparing(t -> {
        if (t.aString.equals("Hi")) {
            return 0;
        }
        if (t.aString.startsWith(" ")) {
            return 1;
        }
        else {
            return 2;
        }
    });
    
    请注意,实际返回的特定数字并不重要,重要的是排序时较低的数字排在较高的数字之前,因此如果总是将字符串“Hi”放在第一位,那么相应的数字应该是返回的最低数字(在我的示例中为0)

    使用Java这是可能的

    使用Java8特性 您可以将函数传递给
    比较器。comparing
    方法来定义规则。请注意,我们只返回整数,即应排在第一位的元素的最低整数

    Comparator<MyClass> myRules = Comparator.comparing(t -> {
        if (t.aString.equals("Hi")) {
            return 0;
        }
        if (t.aString.startsWith(" ")) {
            return 1;
        }
        else {
            return 2;
        }
    });
    
    请注意,实际返回的特定数字并不重要,重要的是排序时较低的数字排在较高的数字之前,因此如果总是将字符串“Hi”放在第一位,那么相应的数字应该是返回的最低数字(在我的示例中为0)

    使用来自MC-emperon的Java非常好(+1),因为它满足了OP不使用java8api的要求。它还使用了一种简洁的内部函数技术(即
    getOrder
    方法),将条件映射到小整数值,以实现一级比较

    这里有一个使用Java8结构的替代方案。它假设
    MyClass
    有一个
    getString
    方法来完成显而易见的事情

        Collections.sort(myList,
            Comparator.comparing((MyClass mc) -> ! mc.getString().equals("Hi"))
                      .thenComparing(mc -> ! mc.getString().startsWith(" "))
                      .thenComparing(MyClass::getString));
    
    这是相当不透明,直到你习惯了这种风格。关键是提供给
    比较器的“提取器”函数。比较
    比较器。然后比较
    通常只提取字段,但它可以是到任何其他值的一般映射。如果该值具有可比性,则无需为其提供额外的比较器。在这种情况下,提取器函数是一个布尔表达式。这将被装箱为一个布尔值,结果是它是可比较的。由于
    false
    true
    之前排序,我们需要对布尔表达式求反

    还要注意,我必须为lambda参数提供一个显式的类型声明,因为类型推断通常不适用于像这样的链式比较器情况。

    来自MC-emperon的示例非常好(+1),因为它满足了OP不使用Java 8 API的要求。它还使用了一种简洁的内部函数技术(即
    getOrder
    方法),将条件映射到小整数值,以实现一级比较

    这里有一个使用Java8结构的替代方案。它假设
    MyClass
    有一个
    getString
    方法来完成显而易见的事情

        Collections.sort(myList,
            Comparator.comparing((MyClass mc) -> ! mc.getString().equals("Hi"))
                      .thenComparing(mc -> ! mc.getString().startsWith(" "))
                      .thenComparing(MyClass::getString));
    
    这是相当不透明,直到你习惯了这种风格。关键是提供给
    比较器的“提取器”函数。比较
    比较器。然后比较
    通常只提取字段,但它可以是到任何其他值的一般映射。如果该值具有可比性,则无需为其提供额外的比较器。在这种情况下,提取器函数是一个布尔表达式。这将被装箱为一个布尔值,结果是它是可比较的。由于
    false
    true
    之前排序,我们需要对布尔表达式求反


    还要注意,我必须为lambda参数提供一个显式的类型声明,因为类型推断通常不适用于像这样的链式比较器情况。

    注意,您将字符串与
    =
    进行比较。永远不要那样做。其次,您应该遵循Java命名约定:类名应该以大写字母开头。第三,可以用lambda表达式替换
    比较器
    (t,u)->{/*您的规则*/return…;}
    @mceponder谢谢您的建议。我会根据你的建议修改这个问题。我对java还是新手
        Collections.sort(myList,
            Comparator.comparing((MyClass mc) -> ! mc.getString().equals("Hi"))
                      .thenComparing(mc -> ! mc.getString().startsWith(" "))
                      .thenComparing(MyClass::getString));