【问题标题】:Ordering with partial explicit and then another order?使用部分显式排序,然后再排序?
【发布时间】:2017-02-08 23:46:13
【问题描述】:

我需要以自定义方式订购列表,我正在研究正确的方式并找到了 guava 的 Ordering api,但问题是我订购的列表并不总是相同的,并且我只需要 2 个字段位于列表顶部,例如我有这个:

List<AccountType> accountTypes = new ArrayList<>();
AccountType accountType = new AccountType();
accountType.type = "tfsa";
AccountType accountType2 = new AccountType();
accountType2.type = "rrsp";
AccountType accountType3 = new AccountType();
accountType3.type = "personal";
accountTypes.add(accountType3);
accountTypes.add(accountType2);
accountTypes.add(accountType);
//The order I might have is : ["personal", "rrsp", "tfsa"]
//The order I need is first "rrsp" then "tfsa" then anything else

我尝试使用自定义比较器并在 Guava 库中使用 Ordering,如下所示:

public static class SupportedAccountsComparator implements Comparator<AccountType> {
    Ordering<String> ordering = Ordering.explicit(ImmutableList.of("rrsp", "tfsa"));
    @Override
    public int compare(AccountType o1, AccountType o2) {
        return ordering.compare(o1.type, o2.type);
    }
}

但它会引发异常,因为显式排序不支持您提供的列表中没有的其他项目,有没有办法进行部分显式排序?类似:

Ordering.explicit(ImmutableList.of("rrsp", "tfsa")).anythingElseWhatever();

【问题讨论】:

标签: java collections guava comparator


【解决方案1】:

您不需要 Guava,您需要的一切都在 Collections API 中。

假设AccountType 实现Comparable,您可以只提供一个Comparator,它返回"tfsa""rrsp" 的最小值,但将其余排序留给AccountType 的默认比较器:

Comparator<AccountType> comparator = (o1, o2) -> {
    if(Objects.equals(o1.type, "rrsp")) return -1;
    else if(Objects.equals(o2.type, "rrsp")) return 1;
    else if(Objects.equals(o1.type, "tfsa")) return -1;
    else if(Objects.equals(o2.type, "tfsa")) return 1;
    else return o1.compareTo(o2);
};
accountTypes.sort(comparator);

如果您不希望对其他项目进行排序,只需提供一个始终返回 0 的默认比较器。

【讨论】:

  • 会试试这个,我有一个这样的比较器,但不是那么干净
  • 哦,我需要 rrsp 然后是 tfsa,但是得到 tfsa 然后是 rrsp,我想改变值就可以了
  • 谢谢你解决了它,我不得不放弃 Objects.equals 因为我使用的是 android SDK 16,但它工作正常。
【解决方案2】:

这是一个Comparator 解决方案,它使用List 字符串来表示您的排序顺序。只需更改 sortOrder 列表中字符串的顺序即可更改排序顺序。

  Comparator<AccountType> accountTypeComparator = (at1, at2) -> {
    List<String> sortOrder = Arrays.asList(
        "rrsp",
        "tfsa",
        "third"
        );
    int i1 = sortOrder.contains(at1.type) ? sortOrder.indexOf(at1.type) : sortOrder.size();
    int i2 = sortOrder.contains(at2.type) ? sortOrder.indexOf(at2.type) : sortOrder.size();
    return i1 - i2;
  };
  accountTypes.sort(accountTypeComparator);

【讨论】:

    猜你喜欢
    • 2016-01-15
    • 1970-01-01
    • 2016-10-15
    • 2011-05-22
    • 2017-02-19
    • 2012-04-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多