如何编写通用比较器,可以对所有必要的字段进行排序?

use*_*934 4 java comparator

我需要在我班级的所有领域实现排序,我为班上的每个领域编写了一个比较器.但我必须为每个字段编写一个单独的比较器.我认为这不是很正确.如何为我的班级编写一个可以对所有字段进行排序的通用比较器?

我的实体:

public class User {
    private long id;
    private String name;
    private int age;
 .....................
Run Code Online (Sandbox Code Playgroud)

我的比较器:

public class UserComparatorById implements Comparator<User> {   
    public int compare(User user1, User user2) {        
       int result = (int)(user1.getId() - user2.getId());
       if (result != 0) return (int)(result/Math.abs(result));        
       result = user1.getName().compareTo (user2.getName());
       if (result != 0) return (int)(result/Math.abs(result));
       result = user1.getAge() - user2.getAge();
       return (result != 0) ? (int)(result/Math.abs(result)) : 0;
    }
}
Run Code Online (Sandbox Code Playgroud)
public class UserComparatorByName implements Comparator<User> { 
    public int compare(User user1, User user2) {            
       int result = user1.getName().compareTo (user2.getName());
       if (result != 0) return (int)(result/Math.abs(result));
       result = (int)(user1.getId() - user2.getId());
       if (result != 0) return (int)(result/Math.abs(result));  
       result = user1.getAge() - user2.getAge();
       return (result != 0) ? (int)(result/Math.abs(result)) : 0;
    }
}
Run Code Online (Sandbox Code Playgroud)
public class UserComparatorByAge implements Comparator<User> {  
    public int compare(User user1, User user2) {            
       int result = user1.getAge() - user2.getAge();
       if (result != 0) return (int)(result/Math.abs(result));
       result = (int)(user1.getId() - user2.getId());
       if (result != 0) return (int)(result/Math.abs(result));   
       result = user1.getName().compareTo (user2.getName());
       return (result != 0) ? (int)(result/Math.abs(result)) : 0;
    }
}
Run Code Online (Sandbox Code Playgroud)

排序:

List<User> users = new ArrayList<User>();

    users.add(new User(5, "Frank", 28));
    users.add(new User(1, "Jorge", 19));
    users.add(new User(6, "Bill", 34));
    users.add(new User(3, "Michel", 17));
    users.add(new User(7, "Mark", 42));

    UserComparatorByName comparatorByName = new UserComparatorByName();
    Collections.sort(users, comparatorByName);

    UserComparatorByAge comparatorByAge = new UserComparatorByAge();
    Collections.sort(users, comparatorByAge);
Run Code Online (Sandbox Code Playgroud)

Tom*_*icz 5

每个字段的一个实现并不是那么糟糕,但是代码中存在大量重复.每个字段应该有一个比较器.如果要基于多个字段进行比较,但顺序不同,请包装原子比较器(装饰器模式):

public abstract class AbstractComparator implements Comparator<User> {
    private final AbstractComparator next;

    public AbstractComparator(AbstractComparator next) {
        this.next = next;
    }

    public int compare(User user1, User user2) {
        int result = doCompare(user1, user2);
        if (result != 0) {
            return result;
        } else {
            return next != null? next.compare(user1, user2) : 0;
        }
    }

    public abstract int doCompare(User user1, User user2);
}
Run Code Online (Sandbox Code Playgroud)
class ById extends AbstractComparator {
    public ById(AbstractComparator next) {
        super(next);
    }

    public int doCompare(User user1, User user2) {
        return (int) (user1.getId() - user2.getId());
    }
}
Run Code Online (Sandbox Code Playgroud)
class ByName extends AbstractComparator {
    public ByName(AbstractComparator next) {
        super(next);
    }

    public int doCompare(User user1, User user2) {
        return user1.getName().compareTo(user2.getName());
    }
}
Run Code Online (Sandbox Code Playgroud)
class ByAge extends AbstractComparator {
    public ByAge(AbstractComparator next) {
        super(next);
    }

    public int doCompare(User user1, User user2) {
        return user1.getAge() - user2.getAge();
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

Comparator<User> comp1 = new ById(new ByName(new ByAge(null)));
Comparator<User> comp2 = new ByAge(new ByName(new ById(null)));
Run Code Online (Sandbox Code Playgroud)

comp1首先通过排序id,如果相等,回落到nameage作为最后的手段.API很清楚.

为方便起见,你应该把所有By*类的静态内部类User:User.ByName,User.ByAge,等,或可能与一些工厂方法:User.byName(User.byAge(null)).在一些静态导入的帮助下,您可以获得愉快的:

Collections.sort(users, byName(byAge(byId(null))));
Run Code Online (Sandbox Code Playgroud)

或者看看Commons Lang的CompareToBuilder.