如何在字段上使用基于规则的计算器对Java对象列表进行排序?
我想使用给定的值对特定字段上对象的如何在字段上使用基于规则的计算器对Java对象列表进行排序?,java,sorting,Java,Sorting,我想使用给定的值对特定字段上对象的ArrayList进行排序 例如,我们有一个对象的列表: public Thing { public String name; public String type; } List<Thing> things = new ArrayList<Thing>(); RuleBasedCollator ruleBasedCollator = new RuleBasedCollator("< Table < Plate &
ArrayList
进行排序
例如,我们有一个对象的列表:
public Thing {
public String name;
public String type;
}
List<Thing> things = new ArrayList<Thing>();
RuleBasedCollator ruleBasedCollator = new RuleBasedCollator("< Table < Plate < Fork < Knife");
公共事物{
公共字符串名称;
公共字符串类型;
}
List things=new ArrayList();
RuleBasedCalator RuleBasedCalator=新的RuleBasedCalator(“
现在,在创建了Thing
对象并将它们添加到things
列表之后,我想对该列表进行排序,获取类型的第一件事物
“table”和类型的最后一件事物“knife”
有人知道怎么做吗?据我所知,RuleBaseCollator
用于排序String
s,至少我在Collator类中是这样说的,它是超类。我会使用一个比较器,类似这样:
public class ThingSorter {
public enum ThingType{
//wanted sort order, sort on ordinal :
//Table < Plate < Fork < Knife
TABLE, PLATE, FORK, KNIFE
}
public static class Thing {
private String name;
private ThingType type;
public Thing(String name, ThingType tt) {
this.name = name;
type = tt;
}
public String toString() {
return name + " [" + type + "]";
}
}
public static class MyThingComparator implements Comparator<Thing> {
@Override
public int compare(Thing t1, Thing t2) {
return t1.type.ordinal() - t2.type.ordinal();
}
}
public static class MyReverseThingComparator implements Comparator<Thing> {
@Override
public int compare(Thing t1, Thing t2) {
return t2.type.ordinal() - t1.type.ordinal();
}
}
public static void main(String[] args) throws ParseException {
List<Thing> things = new ArrayList<Thing>();
things.add(new Thing("One", ThingType.KNIFE));
things.add(new Thing("Two", ThingType.FORK));
things.add(new Thing("Three", ThingType.PLATE));
things.add(new Thing("Four", ThingType.TABLE));
System.out.println("unsorted:\n" + things);
Collections.sort(things, new MyThingComparable());
System.out.println("sorted:\n" + things);
Collections.sort(things, new MyReverseThingComparable());
System.out.println("sorted:\n" + things);
}
public class ThingSorter{
公共枚举类型{
//需要排序顺序,按顺序排序:
//桌<盘<叉<刀
桌子、盘子、叉子、刀
}
公共静态类事物{
私有字符串名称;
私人物品类型;
公共事物(字符串名称,ThingType tt){
this.name=名称;
类型=tt;
}
公共字符串toString(){
返回名称+“[”+类型+“]”;
}
}
公共静态类MyThingComparator实现Comparator{
@凌驾
公共整数比较(t1事物,t2事物){
返回t1.type.ordinal()-t2.type.ordinal();
}
}
公共静态类MyReverseThingComparator实现Comparator{
@凌驾
公共整数比较(t1事物,t2事物){
返回t2.type.ordinal()-t1.type.ordinal();
}
}
公共静态void main(字符串[]args)引发异常{
List things=new ArrayList();
事物。添加(新事物(“一”,事物类型。刀));
添加(新事物(“两个”,ThingType.FORK));
添加(新事物(“三”,ThingType.PLATE));
添加(新事物(“四”,ThingType.TABLE));
System.out.println(“未排序:\n”+事物);
Collections.sort(things,newmythingcomparable());
System.out.println(“排序:\n”+事物);
Collections.sort(things,newMyReverseThingComparable());
System.out.println(“排序:\n”+事物);
}
}
在这种情况下,排序中不涉及名称,只涉及类型(以及类型中的序号)我终于找到了使用树映射的解决方案。我对键使用“type”属性,对值使用事物列表。我没有使用RuleBasedCalator,而是创建了一个ListBasedCalator扩展Collator,因为RuleBasedCalator规则用于字符,而不用于单词
public class ListBasedCollator extends Collator {
private List<String> list;
public ListBasedCollator(String[] array) {
list = Arrays.asList(array);
}
@Override
public int compare(String source, String target) {
if(!list.contains(target)) {
return 1;
}
if(!list.contains(source)) {
return -1;
}
return Integer.valueOf(list.indexOf(source)).compareTo(Integer.valueOf(list.indexOf(target)));
}
@Override
public CollationKey getCollationKey(String source) {
return null;
}
@Override
public int hashCode() {
return 0;
}
公共类ListBasedCollector扩展了Collator{
私人名单;
公共ListBasedCollector(字符串[]数组){
列表=数组。asList(数组);
}
@凌驾
公共整数比较(字符串源、字符串目标){
如果(!list.contains(目标)){
返回1;
}
如果(!list.contains(源)){
返回-1;
}
返回Integer.valueOf(list.indexOf(source)).compareTo(Integer.valueOf(list.indexOf(target)));
}
@凌驾
公共排序规则键getCollationKey(字符串源){
返回null;
}
@凌驾
公共int hashCode(){
返回0;
}
}
下面是我如何构建树映射的:
String[] sortingList = {"TABLE", "PLATE", "FORK", "KNIFE"};
ListBasedCollator listBasedCollator = new ListBasedCollator(sortingList);
Map<String, List<Thing>> thingMap = new TreeMap<String, List<Thing>>(listBasedCollator);
String[]排序列表={“表”、“板”、“叉”、“刀”};
ListBasedCalator ListBasedCalator=新的ListBasedCalator(排序列表);
Map thingMap=新树映射(ListBasedCollector);
因此,thingMap将始终使用ListBasedCalator按类型排序。
我还可以按字母顺序对每种不同类型的列表进行排序。您当然可以按照前面的答案使用TreeMap
或enum
;一个更简单的替代方法是只使用自定义的兼容程序,而不使用enum
。如果您使用的是Java 8,您可以将其简化为一行:
Collections.sort(things,
(Thing t1, Thing t2)->ruleBasedCollator.compare(t1.type, t2.type) );
pre-8版本将对匿名的比较器执行相同的操作,您可以尝试类似的操作,而不是在比较器的compare方法中使用compareTo,您可以调用RuleBasedCalator的compare
mQueue.sort((o1, o2) -> {
if (o1.getDescription().getTitle() != null && o2.getDescription().getTitle() != null) {
return mRuleBasedCollator.compare(o1.getDescription().getTitle().toString(),
o2.getDescription().getTitle().toString());
} else {
return 0;
}
});
非常感谢这个似乎运行良好的解决方案。但是,您可以将我的“type”属性转换为预定义的枚举,在我的例子中,将其保留为字符串很重要。我终于用TreeMap找到了另一个解决方案。非常感谢,我不知道这个新的Java8语法听起来很好。@Raedwald Fromjava.text
: