我有3个数据字段,我们将它们命名为Field 1, Field 2, Field 3
现在让我说我有这些价值观:
Field 1 Field 2 Field 3
1 3 4
2 3 3
3 3 5
4 2 5
如何编写一个比较器,按比例排序Field 1
,如果Field 2
相等,则它将按降序排序Field 3
。结果应该是这样的:
Field 1 Field 2 Field 3
1 3 5
2 3 4
3 3 3
4 2 5
我可能需要交换价值,但这没关系。
答案 0 :(得分:3)
编辑:我误解了这个问题。该解决方案对字段1进行排序,然后是字段2,然后是字段3.这不是OP正在寻找的。 p>
我怀疑你有一个包含这三个字段的Java对象。我假设他们可以通过getter访问。我还假设你的对象存储在某种List中。
您尚未指定所使用的Java版本,因此我将使用Java 8解决方案。这可以与早期版本的Java一起使用,但它会更加冗长。
List<MyObject> myObjects = Arrays.asList(new MyObject(1, 2, 3),
new MyObject(0, 1, 2),
new MyObject(1, 1, 1),
new MyObject(1, 1, 0),
new MyObject(1, 2, 1));
List<MyObject> sortedList = myObjects.stream()
.sorted(Comparator.comparing(MyObject::getField1)
.thenComparing(MyObject::getField2)
.thenComparing(MyObject::getField3))
.collect(Collectors.toList());
System.out.println(sortedList);
该程序输出
[0-1-2, 1-1-0, 1-1-1, 1-2-1, 1-2-3]
此解决方案使用Java 8 Stream API和sorted()
方法,可以轻松对Stream
进行排序。排序是通过使用Comparator
实现的,Comparator
是一个简单的类,可以确定两个实例中哪一个比另一个实例“更大”。
由于Comparator.comparing()
方法,创建基于字段比较实例的Comparator
非常简单。基于多个字段进行比较是使用.thenComparing()
链接返回的import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
public class MyObject
{
private int field1;
private int field2;
private int field3;
public MyObject(int field1,
int field2,
int field3)
{
this.field1 = field1;
this.field2 = field2;
this.field3 = field3;
}
public int getField1()
{
return field1;
}
public int getField2()
{
return field2;
}
public int getField3()
{
return field3;
}
@Override
public String toString()
{
return field1 + "-" + field2 + "-" + field3;
}
public static void main(String[] args)
{
List<MyObject> myObjects = Arrays.asList(new MyObject(1, 2, 3),
new MyObject(0, 1, 2),
new MyObject(1, 1, 1),
new MyObject(1, 1, 0),
new MyObject(1, 2, 1));
List<MyObject> sortedList = myObjects.stream()
.sorted(Comparator.comparing(MyObject::getField1)
.thenComparing(MyObject::getField2)
.thenComparing(MyObject::getField3))
.collect(Collectors.toList());
System.out.println(sortedList);
}
}
的简单过程。
Java 8方法引用用于引用字段的getter。
完整代码:
# (Please note these are statistical summaries, not actual data sets)
x1 = list(stats = matrix(c(1,2,3,4,5)), n = 5)
x2 = list(stats = matrix(c(4,5,6,7,8)), n = 10)
x3 = list(stats = matrix(c(3,4,5,6,7)), n = 15)
x4 = list(stats = matrix(c(2,3,4,5,6)), n = 20)
x5 = list(stats = matrix(c(5,6,7,8,9)), n = 25)
xx1 = list(stats = matrix(c(1.5,2,3,4,4.5)), n = 5)
xx2 = list(stats = matrix(c(4.5,5,6,7,7.5)), n = 10)
xx3 = list(stats = matrix(c(3.5,4,5,6,6.5)), n = 15)
xx4 = list(stats = matrix(c(2.5,3,4,5,5.5)), n = 20)
xx5 = list(stats = matrix(c(5.5,6,7,8,8.5)), n = 25)
## gather up the data
ll <- mget(ls(pattern = '^x\\d'))
l1 <- list(stats = do.call('cbind', lapply(ll, '[[', 1)),
n = unlist(lapply(ll, '[[', 2)))
ll <- mget(ls(pattern = 'xx\\d'))
l2 <- list(stats = do.call('cbind', lapply(ll, '[[', 1)),
n = unlist(lapply(ll, '[[', 2)))
## plot
par(mfrow = c(2, 1), mar = c(2,5,1,1))
bxp(l1, ylab = 'x values', xaxt = 'n')
par(mar = c(2,5,0,1)) ## keep space for group labels
bxp(l2, ylab = 'xx values', xaxt = 'n')
mtext(at = 1:5, side = 1, text = paste('Group', 1:5), line = .5)
答案 1 :(得分:1)
我会分两部分来做。第1部分将基于字段1进行排序。
第2部分将涉及创建一个映射(HashMap
),其中字段2的值作为映射到字段3值的二进制堆(PriorityQueue
)的键,按相反顺序排序。然后,我会迭代原始数组,并将字段3替换为字段2堆顶部的元素。
答案 2 :(得分:0)
在阅读了对早期答案的回复之后,我认为你是在采用两次通过方式之后。首先,您要按第一个字段对对象列表进行排序。然后你想回到集合中,如果两个项目具有相同的字段2,我们按字段3排序。
所以这是最简单的方法,使用两个不同的比较器对集合进行两次排序,第一个按字段1排序:
@Override
public int compare(MyObject o1, MyObject o2) {
return Integer.compare(o1.getFieldOne(), o2.getFieldOne());
}
第二个仅在第二个字段相等时按字段三进行排序
@Override
public int compare(MyObject o1, MyObject o2) {
int secondFieldComparison = Integer.compare(o1.getFieldTwo(), o2.getFieldTwo());
if (secondFieldComparison == 0) {
return Integer.compare(o1.getFieldThree(), o2.getFieldThree());
} else {
return 0;
}
}