根据两个条件对列表进行排序

Sort a list based on two conditions

所以,我不知道是否有一个优雅的解决方案,但这里是。我想对列表进行排序,但该列表包含三种类型的项目。我想要的是类型 A 按字母顺序排列在顶部,类型 B 和 C 位于底部并按字母顺序排列(类型 B 和 C 将合并)。

这是我的代码:

public int compareTo(Friendship another) {
    if(this.getType().equals(TypeA) &&
            another.getType().equals(TypeA)){ //if they are both type A, just sort based on user name

        return this.getUsername().compareTo(
                another.getUsername());
    }
    else if(this.getType.equals(TypeA)){ 
        return -1;
    }
    else if(another.getType().equals(TypeA)){
        return 1;
    }
    else{ //this will be hit if they are either Type B or C, then just sort based on username
        return this.getUsername().compareTo(
                another.getUsername());
    }
}

编辑:抱歉,我应该更好地解释这一点。问题是上面的代码不起作用。据我所见,该列表似乎没有正确排序。 由于某种原因,TypeA 列表的顺序与我想要的相反(Z -> A)。而 TypeB & C 列表只排序了一半。所以我假设我的代码中存在错误。如果您需要更多信息,请告诉我

EDIT2:对样本进行了更多测试,看起来字符串根本没有被排序。我都做了

this.getUsername().compareTo(
            another.getUsername());

another.getUsername().compareTo(
            this.getUsername());

编辑 3:你们是对的。我的代码中的其他地方有一个错误(这是不相关的)。抱歉......在这种情况下也不知道该怎么办。我应该给谁正确的答案?

我在同样的情况下使用了类似的解决方案,我觉得很好。

但代码可以更短:

public int compareTo(Friendship another) {
    boolean thisOnTop = getType().equals(TypeA);
    boolean anotherOnTop = another.getType().equals(TypeA);
    if (thisOnTop != anotherOnTop) {
        return thisOnTop ? -1 : 1;
    } else {
        return this.getUsername().compareTo(another.getUsername());
    }
}

如果我是你,我不会改结构,只会优化这点

public int compareTo(Friendship another) {


       if(!this.getType().equals(another.getType()){
        //if type are not equal, so we might have at most one A

          if(this.getType.equals(TypeA)){ //on left side
             return -1;
          }

          if(another.getType().equals(TypeA)){ //or, on rightside
            return 1;
          }
        }
          //or we have on both sides or neither side
            return this.getUsername().compareTo(
                    another.getUsername());
        }

您只需按照您所说的逻辑在 3 类 中实现您的 compareTo。像这样:

// TypeA.class
// TypeA class will have priority over the other two, so just sort by whatever you want
public int compareTo(AnotherType anotherType) {
    if (this.equals(anotherType)) // TypeA vs TypeA - alphabetically
        return this.getUsername().compareTo(anotherType.getUsername());
    else // otherwise typeA is greater
        return 1; // 1 means greater than
}

// TypeB.class
public int compareTo(AnotherType anotherType) {
    if (this.equals(anotherType)) // both typeB, sort alphabetically
        return this.getUsername().compareTo(anotherType.getUsername());
    else
        if(this.equals(typeC)) // TypeB vs TypeC, alphabetically
            return this.getUsername().compareTo(typeC.getUsername());
        else // TypeB vs TypeA
            return -1; // -1 means lesser than
}

//TypeC.class
public int compareTo(AnotherType anotherType) {
    if (this.equals(anotherType)) // TypeC vs TypeC - alphabetically
        return this.getUsername().compareTo(anotherType.getUsername());
    else
    if(this.equals(typeB)) // TypeC vs TypeB - alphabetically
        return this.getUsername().compareTo(typeB.getUsername());
    else
        return -1; // -1 means lesser than
}

有一个优雅的方法可以解决这个问题,它不涉及丑陋的 compareTo trainwrecks。

  1. 通过您的列表并制作 2 个 SortedSet,一个用于 A,一个用于 B + C。根据类型添加您的好友。
  2. 创建一个新列表并使用 Collections.addAll() 方法将您可以从 2 SortedSet 获得的 2 个数组添加到列表中,首先是 A 的数组,然后是 A 的数组对于 B+C

因为 SortedSet 会保持内容的自然顺序,对于字符串来说是字典序的,你的最终列表将有类型 A 在前,按字典顺序排序,在 B and C 之后,也排序按字典顺序。