如何按月和日期对日期进行排序日但不包括年份

时间:2013-10-11 20:49:14

标签: java

我必须通过Birthdate对人物对象的集合进行排序,因此我创建了以下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日......

我现在拥有它的方式,因为这一年是可比的日期从最古老的一年到最近一年的一部分。

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

3 个答案:

答案 0 :(得分:4)

  

这可以用来分拣出生日期,但需要额外的   我要求的是按出生日期最接近的方式对它们进行排序   今天上升。因此,例如,如果今天是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 - &gt; JAN 20, FEB 5, SEP 18, OCT 9

正式 ,根据月份和日期找到我们的数据透视表中即刻较大日期i的索引comparing(尝试使用compareTo示例),然后创建一个新列表,插入元素从索引i开始到n-1,然后0i-1,这里n的大小是出生日期清单。

我希望有所帮助。

答案 1 :(得分:1)

写一个Comparator

您可以为人员指定一个比较器,其中包括年份,另一个比较器将其排除。

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

Collections.sort(list, new BirthdayWithoutYearComparatr());

答案 2 :(得分:1)

你有一系列复杂的问题。

首先,我个人不会制作PersonComparable,主要问题(我看到这个)是,它并不是真正比较Person对象,而是只是其中一个属性。这会阻止您进行可能无法满足您所有要求的比较。

相反,我会建立一系列Comparator来完成非常具体的工作,例如,比较Person的出生日期。

下一个问题是类似的API不支持不匹配的参数,好吧,确实如此,但它很麻烦......

我们需要的是一些方法,我们可以将对象(或更具体地说,对象的属性)与其他值进行比较。

现在,因为核心API是基于比较相似的值,我们需要提供自己的实现来支持我们的需求。

因此,下面是一个快速排序实现,允许您提供List个对象ISortMatcher和要与之比较的值(这是所有值的基值)列表将与之比较)

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之前,因为它距离目标日期更近......