自定义比较器用于多字段排序

huangapple go评论78阅读模式
英文:

Custom Comparator sort with multiple fields

问题

因为这个问题与我上一个问题相关,我会在这里链接上

假设我有一个包含两个整数的类TestB。我可以像这样对List<TestB> list按照a,然后按照b进行排序:

list.sort(Comparator.comparing(TestB::getA).thenComparing(TestB::getB));

现在我想知道如何在上一个回答中使用自定义比较器来实现这一点。

英文:

Because this question is related to my last one, I will link it here.

Suppose I have a class TestB with two integers. I would be able to sort List<TestB> list on a and then on b like this:

list.sort(Comparator.comparing(TestB::getA).thenComparing(TestB::getB));

Now I want to know how to do that with the custom comparator in the last answer.

答案1

得分: 2

自定义的Comparator版本为list.sort(Comparator.comparing(TestB::getA).thenComparing(TestB::getB));

list.sort(new Comparator<>() {
	@Override
	public int compare(TestB b1, TestB b2) {
		int cmp = b1.getA().compareTo(b2.getA());
		if (cmp == 0)
			cmp = b1.getB().compareTo(b2.getB());
		return cmp;
	}
});
英文:

The custom Comparator version of list.sort(Comparator.comparing(TestB::getA).thenComparing(TestB::getB)); is:

list.sort(new Comparator&lt;&gt;() {
	@Override
	public int compare(TestB b1, TestB b2) {
		int cmp = b1.getA().compareTo(b2.getA());
		if (cmp == 0)
			cmp = b1.getB().compareTo(b2.getB());
		return cmp;
	}
});

答案2

得分: 0

一个选项是使用我称之为自定义通用多比较器:

list2.sort(getComparator(p -> p.getTestB().getA(),
    p -> p.getTestB().getB()));

private <T> Comparator<T> getComparator(Function<T, ? extends Comparable<?>>... functions) {
    
    return new Comparator<T>() {
        @Override
        public int compare(T obj1, T obj2) {
            
            for (Function<T, ? extends Comparable<?>> function : functions) {
                Comparable<?> res1 = (Comparable<?>) function.apply(obj1);
                Comparable<?> res2 = (Comparable<?>) function.apply(obj2);
                
                int result = res1.compareTo((T) res2);
                
                if (result != 0) {
                    return result;
                }
            }
            
            return 0;
        }
    };
}

它将根据函数参数的放置顺序从左到右排序。尽管会出现警告,因为它非常通用。
请记住,要比较的最终值的类型必须实现Comparator(像Integer这样的原始类型已经实现了),并且您应该处理null问题(我在这里没有处理以保持简短)。

英文:

One option is to use what I call a custom generic multi-comparator:

list2.sort(getComparator( p -&gt; p.getTestB().getA(),
    p -&gt; p.getTestB().getB() ));

private &lt;T&gt; Comparator&lt;T&gt; getComparator( Function&lt;T, ? extends Comparable&lt;?&gt;&gt;... functions ) {
    
    return new Comparator&lt;T&gt;() {
        @Override
        public int compare(T obj1, T obj2) {
            
            for (Function&lt;T, ? extends Comparable&lt;?&gt;&gt; function : functions) {
                Comparable&lt;T&gt; res1 = (Comparable&lt;T&gt;) function.apply(obj1);
                Comparable&lt;T&gt; res2 = (Comparable&lt;T&gt;) function.apply(obj2);
                
                int result = res1.compareTo((T) res2);
                
                if ( result != 0 ) {
                    return result;
                }
            }
            
            return 0;
        }
    };
}

It will sort from left to right regarding the order which function parameters are placed. Warnings will be raised although. Because it's very generic.
Keep in mind that the types of the final values to be compared must implement Comparator (which primitive types like Integer already do) and you should deal with null problems (I didn't do it here to keep it short).

huangapple
  • 本文由 发表于 2020年8月28日 04:20:52
  • 转载请务必保留本文链接:https://go.coder-hub.com/63623662.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定