你有一系列复杂的问题。
首先,我个人不会将Person
class 设为Comparable
主要问题(我看到了这个),它并不是真正比较Person
对象,而只是比较它的一个属性。这会将您锁定在可能无法始终满足所有要求的比较中。
相反,我个人会设置一系列Comparator
s 来完成非常具体的工作,例如比较Person
.
下一个问题是可比较的 API 不支持不匹配的参数,好吧,它支持,但它很混乱......
我们需要的是某种可以将对象(或更具体地说,对象的属性)与其他值进行比较的方法。
现在,因为核心 API 是基于比较相似的值,我们需要提供自己的实现来支持我们的需求。
因此,下面是一个快速排序实现,它允许您提供一个List
对象 aISortMatcher
和一个要比较的值(这是列表中所有值将被比较的基本值)
import java.util.Collections;
import java.util.List;
public class QuickSort {
public static <O, M> void sort(List<O> values, M value, ISortMatcher<O, M> matcher) {
sort(values, value, matcher, 0, values.size() - 1);
}
protected static <O, M> void sort(List<O> values, M value, ISortMatcher<O, M> matcher, int low, int high) {
int i = low, j = high;
// Get the pivot element from the middle of the list
int pivot = matcher.compare(values.get(low + (high - low) / 2), value);
// Divide into two lists
while (i <= j) {
// If the current value from the left list is smaller then the pivot
// element then get the next element from the left list
while (matcher.compare(values.get(i), value) < pivot) {
i++;
}
// If the current value from the right list is larger then the pivot
// element then get the next element from the right list
while (matcher.compare(values.get(j), value) > pivot) {
j--;
}
// If we have found a values in the left list which is larger then
// the pivot element and if we have found a value in the right list
// which is smaller then the pivot element then we exchange the
// values.
// As we are done we can increase i and j
if (i <= j) {
Collections.swap(values, i, j);
i++;
j--;
}
}
// Recursion
if (low < j) {
sort(values, value, matcher, low, j);
}
if (i < high) {
sort(values, value, matcher, i, high);
}
}
public static interface ISortMatcher<O, M> {
public int compare(O o, M m);
}
}
好的,这是排序的一个非常具体的要求,有点像二分搜索,但它会......
这允许我们做的是定义我们想要匹配的基值、执行比较的算法以及要排序的值列表。它的工作原理与核心 API 类似,返回小于、等于或大于 0 的值以指示结果的权重。
现在,我们可以开始比较...
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
public class SortDates {
public static final SimpleDateFormat SDF = new SimpleDateFormat("dd/MM/yyyy");
public static void main(String[] args) {
new SortDates();
}
public SortDates() {
List<Person> people = new ArrayList<Person>(5);
for (int index = 0; index < 10; index++) {
Date date = getDate(
(int)(Math.random() * 30) + 1,
(int)(Math.random() * 12),
(int)(Math.random() * 113) + 1900);
people.add(new Person(date));
}
Collections.sort(people, new DateOfBirthComparator());
System.out.println("By date of birth");
for (Person p : people) {
System.out.println(p);
}
Collections.shuffle(people);
System.out.println("");
System.out.println("Shuffled");
for (Person p : people) {
System.out.println(p);
}
QuickSort.ISortMatcher matcher = new QuickSort.ISortMatcher<Person, Date>() {
@Override
public int compare(Person o, Date m) {
Calendar with = Calendar.getInstance();
with.setTime(m);
Calendar to = Calendar.getInstance();
to.setTime(o.getBirthDate());
to.set(Calendar.YEAR, with.get(Calendar.YEAR));
int withDOY = with.get(Calendar.DAY_OF_YEAR);
int toDOY = to.get(Calendar.DAY_OF_YEAR);
int result = 0;
if (withDOY < toDOY) {
result = toDOY - withDOY;
} else if (withDOY > toDOY) {
result = withDOY - toDOY;
}
return result;
}
};
QuickSort.sort(people, new Date(), matcher);
System.out.println("");
System.out.println("To today (" + SDF.format(new Date()) + ")");
for (Person p : people) {
System.out.println(p);
}
}
public Date getDate(int day, int month, int year) {
Calendar cal = Calendar.getInstance();
cal.set(Calendar.DATE, day);
cal.set(Calendar.MONTH, month);
cal.set(Calendar.YEAR, year);
return cal.getTime();
}
public class Person {
private Date birthDate;
public Person(Date birthDate) {
this.birthDate = birthDate;
}
@Override
public String toString() {
return SDF.format(birthDate);
}
public Date getBirthDate() {
return birthDate;
}
}
public class DateOfBirthComparator implements Comparator<Person> {
@Override
public int compare(Person o1, Person o2) {
return o1.getBirthDate().compareTo(o2.getBirthDate());
}
}
}
该示例的核心是QuickSort
Matcher
. 这决定了在给定值和我们要用作比较基础的值之间应用的权重。
QuickSort.ISortMatcher matcher = new QuickSort.ISortMatcher<Person, Date>() {
@Override
public int compare(Person o, Date m) {
Calendar with = Calendar.getInstance();
with.setTime(m);
Calendar to = Calendar.getInstance();
to.setTime(o.getBirthDate());
to.set(Calendar.YEAR, with.get(Calendar.YEAR));
int withDOY = with.get(Calendar.DAY_OF_YEAR);
int toDOY = to.get(Calendar.DAY_OF_YEAR);
int result = 0;
if (withDOY < toDOY) {
result = toDOY - withDOY;
} else if (withDOY > toDOY) {
result = withDOY - toDOY;
}
return result;
}
};
现在,我已经从字面上理解了您的要求,这将根据它们与给定的距离对值进行排序Date
,因此您最终可能会得到指定日期之前的日期出现在指定日期之后的日期之后......
例如,
By date of birth
05/10/1905
01/10/1906
13/03/1921
11/04/1942
07/12/1944
27/04/1953
05/07/1988
15/12/1988
19/03/1995
12/07/2001
Shuffled
13/03/1921
01/10/1906
05/07/1988
12/07/2001
11/04/1942
27/04/1953
19/03/1995
15/12/1988
07/12/1944
05/10/1905
To today (12/10/2013)
05/10/1905
01/10/1906
07/12/1944
15/12/1988
12/07/2001
05/07/1988
27/04/1953
11/04/1942
19/03/1995
13/03/1921
您可以看到它05/10
出现在之前07/12
,因为它更接近目标日期......