Android - java - 如何通过GregorianCalendar参数对对象列表进行排序

时间:2017-03-02 00:25:00

标签: java android sorting collections calendar

我想显示按日期顺序的日期参数排序的对象列表。 我尝试了很多方法。但它不起作用。它不会改变列表中对象的顺序。 我访问了这个寻求帮助: Android: How to sort list items according to dates

How to Sort Date in descending order From Arraylist Date in android?

https://www.quora.com/How-do-I-sort-an-ArrayList-of-objects-by-each-objects-integer-parameter

这是我的代码:

我的班级对象

public class Evento extends GregorianCalendar {

public Calendar date;
public String tipo = " ";
public String a = " ";
public String b = " ";
public String c = " ";

我的MainActivity:

public void implementList (View view){

    List <Evento> listEventosAll = new ArrayList<>();

    listEventosAll.addAll(listEventos1);

    listEventosAll.addAll(listEventos2);

    Collections.sort(listEventosAll,  new Comparator<Evento> (){
         public int compare(Evento evento1, Evento evento2) {
             if (evento1.date.getTime() == null || evento2.date.getTime() == null)
                 return 0;
             return evento1.date.getTime().compareTo(evento2.date.getTime());
        }

   }); 


    EventoAdapter adapter = new EventoAdapter(this,listEventosAll);
    ListView listView = (ListView) findViewById(R.id.listView);
    listView.setAdapter(adapter);
}

填充ListEventos1

public static Evento setEvento(Calendar day, String a, String b) {

Evento evento = new Evento();
evento.date = day;
evento.a = a;
evento.b = b; 
return evento;

}

//创建列表:

public static ArrayList listEventos1(int year){

Calendar day = calculateCertainTuesday(year);

ArrayList <Evento> list = new ArrayList<Evento>();

list.add(setEvento(day, "Certain Tuesday”, "do this"));

day.add(Calendar.DAY_OF_MONTH, 1); 

list.add(setEvento(day, "Certain Wendsday”, "do that"));

day.add(Calendar.DAY_OF_MONTH,-2); 

list.add(setEvento(day, "Certain Monday", "do what"));


day.add(Calendar.DAY_OF_MONTH, -1); 

list.add(setEvento(day, "SUNDAY", "don’t do"));


return list;

}

1 个答案:

答案 0 :(得分:1)

编辑我完整地回答了我的回答,以回应您问题的新修改。

问题在于,对于填充Evento的每个listEventos1,您使用相同的Calendar(变量名称day)。你这样做了:

list.add(setEvento(day, "Certain Tuesday”, "do this"));

然后这个:

day.add(Calendar.DAY_OF_MONTH, 1); 
list.add(setEvento(day, "Certain Wendsday”, "do that"));

但是对Calendar#add的呼吁是什么呢

  

将指定的时间量添加或减去给定日历   字段,基于日历的规则。

换句话说,Calendar是一个可变类,即它可以改变状态,不像String,它是不可变的并且会总是一样的。别担心,你不是第一个犯这个错误的人,partly why Java introduced a new Date API(更准确地说,这是因为这使得这些类不是线程安全的)

换句话说,每当您调用Calendar#add方法时,listEventos1中的所有对象都会发生变化,因为它们都包含{{1}的相同实例1}}。有关发生这种情况的一个非常好的示例,请参阅this answer

验证这一点的一种方法是使用Calendar运算符在Comparator中添加补充检查。如果两个变量指向相同的实例,则==将返回true:

==

使用当前代码运行此代码应该输出一堆警告。

另一小撮信息:根据Collections.sort(listEventosAll, new Comparator<Evento> (){ public int compare(Evento evento1, Evento evento2) { if(evento1.date.getTime() == evento2.date.getTime()) System.out.println("Warning! Two references pointing to the same object!"); if (evento1.date.getTime() == null || evento2.date.getTime() == null) return 0; return evento1.date.getTime().compareTo(evento2.date.getTime()); } 的{​​{3}},Comparator如果其中一个参数为Comparator#compare,则应抛出NullPointerException

<强>解 要解决此问题,您需要在每次调用null时传递Calendar的不同实例。某些类(例如Collection API中的类)拥有复制构造函数,即将对象作为参数的构造函数,并返回具有完全相同的 new 对象值。 setEvento没有实现复制构造函数,但它实现了Calendar接口,这意味着您可以克隆其对象。

Java世界中的克隆有时是Javadoc,但在这种特定情况下frowned upon

所以这里是如何克隆Cloneable以便每次调用day时,它指向一个新对象(这是您的Evento方法):

listEventos1

当然,对插入的每个对象重复此操作。

注意: btw,代码中的某些引号正在关闭英文引号(list.add(setEvento(day, "Certain Tuesday", " do this ")); day = (Calendar) day.clone(); //This is what I added day.add(Calendar.DAY_OF_MONTH, 1); )而不是双引号()。这会破坏你的代码。

其他注意:您未正确使用继承机制,并且可以使用"作为Evento本身来简化您的代码。但那是另一天。