在列的基础上排序而不是按字母顺序排序

时间:2014-07-17 07:20:34

标签: java sorting

我有一个名为漏洞的bean。它有一个列“严重性”。

private String severity;

严重性可以包含字符串值High,Medium和Low。现在每当根据严重性列对该bean进行排序时,它按字母顺序排列即高,低和中等。但我希望排序在下降时发生高,中,低,在升序时发生低,中,高。 我看到比较器进行这种自定义排序,但它需要涵盖很多案例。不是他们的任何其他方式吗?

5 个答案:

答案 0 :(得分:1)

compareTo上定义了隐式enum运算符takes their declaration order to mean "smaller than"无需其他代码。

enum Severity { Low, Medium, High }

Low.compareTo(High);   // returns -1
Medium.compareTo(Low); // returns 1

但请注意,枚举常量的名称将是toString()打印的名称(因此,如果您直接回显枚举,则对用户可见) - 如果您想使用不同的内部和外部名称,可能要坚持代码约定(比如all-caps-constants),然后你需要添加一个枚举构造函数并覆盖枚举的toString方法来使用传入的构造函数属性。


如果您无法使用枚举,则无法更改您的bean

然后为它构建一个Comparator:

public class SeverityComparator implements Comparator<String> {
     private int direction;

     public SeverityComparator(boolean reverse) {
         this.direction = reverse ? -1 : 1;
     }

     private int severity(String s) {
         if (s.equals("Low")) { // you really should have constants for the values...
             return 0;
         } else if (s.equals("Medium")) {
             return 1;
         } else if (s.equals("High")) {
             return 2;
         } else {
             throw new IllegalArgumentException("Not a severity: " + s);
         }
     }

     @Override
     public int compareTo(String other) {
         return direction * (severity(this) - severity(other));
     }
}

用作

Collections.sort(listOfSeverities, new SeverityComparator(false)); // ascending
Collections.sort(listOfSeverities, new SeverityComparator(true)); // descending  

答案 1 :(得分:0)

你可以(并且应该)使用枚举 - 不是字符串也不是int:

enum Severity {
    LOW, MEDIUM, HIGH;
}

<强>用法:

    List<Severity> lst = new ArrayList<Severity>();
    lst.add(Severity.MEDIUM);
    lst.add(Severity.LOW);
    lst.add(Severity.HIGH);
    for (Severity s : lst)
        System.out.println("s = " + s);

    Collections.sort(lst);

    System.out.println();

    for (Severity s : lst)
        System.out.println("s = " + s);

<强>输出:

s = MEDIUM
s = LOW
s = HIGH

s = LOW
s = MEDIUM
s = HIGH

修改

由于OP说他无法修改字符串的使用,我们可以将字符串映射到可比较的值:

static Map<String, Integer> severities = new HashMap<String, Integer>();

static {
    severities.put("LOW",1);
    severities.put("MEDIUM",2);
    severities.put("HIGH",3);
}

public static void main(String[] args) {
    List<String> lst = new ArrayList<String>();
    lst.add("MEDIUM");
    lst.add("LOW");
    lst.add("HIGH");
    for (String s : lst)
        System.out.println("s = " + s);

    Collections.sort(lst, new Comparator<String>() {
        public int compare(String a1, String a2) {
            Integer v1 = severities.get(a1);
            Integer v2 = severities.get(a2);
            return v1.compareTo(v2);
        }
    });

    System.out.println();

    for (String s : lst)
        System.out.println("s = " + s);

}

如果您想按降序排列项目,可以排序然后反转:

    Collections.sort(lst);
    Collections.reverse(lst);

答案 2 :(得分:0)

@alfasin答案是正确的,但我建议使用番石榴的订购:

    import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Ordering;

import javax.annotation.Nullable;
import java.util.List;

public class SeveritySortTest {

    private static final List<Severity> SEVERITY_LIST = ImmutableList.copyOf(Severity.values());

    public static void main(String[] args) {

        Ordering<Severity> severityOrdering = Ordering.natural().onResultOf(new Function<Severity, Integer>() {
            @Nullable
            @Override
            public Integer apply(@Nullable Severity input) {
                return input.getSeverity();
            }
        });

        List<Severity> sortedAscending = severityOrdering.sortedCopy(SEVERITY_LIST);
        List<Severity> sortedDescending = severityOrdering.reverse().sortedCopy(SEVERITY_LIST);

    }


    enum Severity {
        LOW(1), MEDIUM(2), HIGH(3);

        private int severity;

        Severity(int s) {
            severity = s;
        }

        int getSeverity() {
            return severity;
        }
    }
}

答案 3 :(得分:0)

工作解决方案:

Collections.sort(推荐,新的Comparator(){

            private int priority(String s) {
                if (s.equalsIgnoreCase("Low")) {
                    return 1;
                } else if (s.equalsIgnoreCase("Medium")) {
                    return 2;
                } else if (s.equalsIgnoreCase("High")) {
                    return 3;
                } else {
                    return 0;
                }
            }

            @Override
            public int compare(Recommendation o1, Recommendation o2) {
                return -1 * (priority(o1.getPriority()) - priority(o2.getPriority()));
            }
        });

答案 4 :(得分:0)

如果您希望数据库通过JPA / Hibernate进行此操作,则可以基于简单的case语句创建一个排序表达式,假设您的实体称为Case:

Expression exp = criteriaBuilder.selectCase(root.get(Case_.priority)).when("High", 1).when("Medium", 2).otherwise(3);
queryBuilder.orderBy(orderDir.isAscending() ? criteriaBuilder.asc(exp) : criteriaBuilder.desc(exp));

在order by子句中使用case语句不利于性能,但可以解决问题。与Oracle配合使用。