1

我必须按生日对一组人员对象进行排序,所以我创建了以下 pojo。

    public class Person implements Comparable<Person> {

    private long id;
    private String name;
    private Date birthDate;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Date getBirthDate() {
        return birthDate;
    }

    public void setBirthDate(Date birthDate) {
        this.birthDate = birthDate;
    }

    @Override
    public int compareTo(Person person) {
        if (getBirthDate() == null || person.getBirthDate() == null)
            return 0;
        return getBirthDate().compareTo(person.getBirthDate());
    }
}

这可以对出生日期进行排序,但我还有一个额外的要求是按照最接近今天升序的出生日期对它们进行排序。例如,如果今天是 10 月 11 日,那么生日将作为示例进行排序。

10 月 20
日 11 月 5
日 1 月 3 日...

以我目前的方式,因为年份是可比日期的一部分,从最早的年份到最近的年份。

我如何在没有年份的情况下对这些生日进行排序?

4

3 回答 3

5

这可以对出生日期进行排序,但我还有一个额外的要求是按照最接近今天升序的出生日期对它们进行排序。因此,例如,如果今天是 10 月 11 日,那么生日将作为示例进行排序

如果我理解正确,那么在排序时您没有考虑年份,例如 1975 年还是?在我看来,您正在使用生日记忆功能。但是,如果您基于 进行排序month and day,则以下comparedTo()函数应该会给您一些想法,以便您根据月份和日期进行比较,不包括年份:

  class Person implements Comparable<Person>
  {
        Date birthDay;
        static SimpleDateFormat formatter = new SimpleDateFormat("MMM dd, yyyy");

        public Person(String birthDay) throws ParseException
       {
             this.birthDay = formatter.parse(birthDay); 

        }        

        @Override
        public int compareTo(Person o) {
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(this.birthDay);
        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(o.birthDay);

        int month1 = cal1.get(Calendar.MONTH); 
        int month2 = cal2.get(Calendar.MONTH);

        if(month1 < month2)  
          return -1;
        else if(month1 == month2)
          return cal1.get(Calendar.DAY_OF_MONTH) - cal2.get(Calendar.DAY_OF_MONTH);

        else return 1;

      }
}

尝试使用以下代码测试:

List<Person>persons = new ArrayList<>();

 persons.add(new Person("MAR 2, 2001"));
 persons.add(new Person("JAN 7, 1972"));
 persons.add(new Person("JAN 2, 1976"));
 persons.add(new Person("MAR 4, 1985"));

 Collections.sort(persons);

 for(Person p : persons)
   System.out.println(p.formatter.format(p.birthDay));
                 //Person.formatter is SimpleDateFormat with format "MMM dd, yyyy" 
                 // in person class, i declared it as static

输出

Jan 02, 1976
Jan 07, 1972
Mar 02, 2001
Mar 04, 1985

使列表根据枢轴排序,例如 OCT 11

我认为在对列表进行排序之后,您可以将其四舍五入,认为它是循环的。例如假设排序列表:

JAN 20, FEB 5, SEP 18, OCT 9, OCT 20, NOV 23

如果我们的支点OCT 11选择直接较大(大于支点的最小日期)日期, 则为OCT 20. 您只需使用for loop. 现在,我们只需要将它四舍五入,认为它是圆形的:

OCT 20, NOV 23-->JAN 20, FEB 5, SEP 18, OCT 9

形式上,根据月份和日期找到我们枢轴i的直接较大日期的索引开始然后到,这里是出生的大小日期列表。comparingin-10i-1n

我希望这会有所帮助。

于 2013-10-11T22:30:38.890 回答
2

写一个比较器

您可以为 Persons 指定一个比较器,其中包括年份,另一个不包括它。

您需要通过调用以下方式对您的列表进行排序:

Collections.sort(list, new BirthdayWithoutYearComparatr());
于 2013-10-11T20:54:44.360 回答
1

你有一系列复杂的问题。

首先,我个人不会将Personclass 设为Comparable主要问题(我看到了这个),它并不是真正比较Person对象,而只是比较它的一个属性。这会将您锁定在可能无法始终满足所有要求的比较中。

相反,我个人会设置一系列Comparators 来完成非常具体的工作,例如比较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,因为它更接近目标日期......

于 2013-10-12T01:19:48.517 回答