假设我有一个列表(或Set):
List<String> testList = Lists.newArrayList("assocX","srcT","destA","srcX", "don't care Y", "garbage", "srcB");
我想找回一个ImmutableList(Set),它按照自然顺序对术语进行排序/分组,其中以“src”开头的术语是第一个,“assoc”第二个和“dest”最后一个。如果术语不包含那些术语,则应将其从结果列表中删除。
因此这里的结果是“srcB”,“srcT”,“assocX”,“destA”。
我想我可以通过Iterables.filter或Predicates的某些组合来做到这一点,但只是没有看到它。我认为必须有一种简洁的方法。
编辑:代替列表的集合也适用。
答案 0 :(得分:33)
只要这三个前缀是你唯一关心的事情,我建议这样:
Predicate<String> filter = new Predicate<String>() {
@Override
public boolean apply(String input) {
return input.startsWith("src") || input.startsWith("assoc") || input.startsWith("dest");
}
};
Function<String, Integer> assignWeights = new Function<String, Integer>() {
@Override
public Integer apply(String from) {
if (from.startsWith("src")) {
return 0;
} else if (from.startsWith("assoc")) {
return 1;
} else if (from.startsWith("dest")) {
return 2;
} else {
/* Shouldn't be possible but have to do something */
throw new IllegalArgrumentException(from + " is not a valid argument");
}
}
};
ImmutableList<String> sortedFiltered = ImmutableList.copyOf(
Ordering.natural().onResultOf(assignWeights).sortedCopy(
Iterables.filter(testList, filter)
)
);
如果您开始添加更多前缀来过滤或排序,此解决方案肯定不会非常好地扩展,因为您必须不断更新过滤器和每个前缀的权重。
答案 1 :(得分:12)
查看This Google Collections example。
Function<Fruit, String> getNameFunction = new Function<Fruit, String>() {
public String apply(Fruit from) {
return from.getName();
}
};
Ordering<Fruit> nameOrdering = Ordering.natural().onResultOf(getNameFunction);
ImmutableSortedSet<Fruit> sortedFruits = ImmutableSortedSet.orderedBy(
nameOrdering).addAll(fruits).build();
尽管如此,诚然,它会返回一个Set。
答案 2 :(得分:0)
我认为您将首先使用谓词来消除您不想要的元素,并实现Comparator并对列表进行排序。
答案 3 :(得分:0)
通常,设计清晰明确的数据是不好的设计。在您的情况下,当您说“assocX”时,“assoc”与“X”具有单独的含义,但您将它们合并在一起。
所以我建议设计一个有两个字段的类。然后你可以在第一个字段上创建一个排序,在另一个字段上创建另一个排序,并将它们组合起来(例如Ordering#compound())。使用toString()方法, 将这些字段合并为一个字符串。作为奖励,这可以通过共享大大减少内存使用。
所以你要对这些对象的列表进行排序,如果你想打印它们,你只需要对它们调用toString()。