Android - 如何按日期对arrayList进行排序?

5
我正在尝试按日期对我的arrayList进行排序。每次我收到通知并从Firebase检索时,我都会将日期存储在那里。我正在使用Collections.sort,但我不知道如何在我的代码中实现,因为我的日期格式以字符串格式的数字开头,如“2017年7月12日上午12:00”。
我在stackoverflow上看到了一些示例,但我不知道如何使其在我的情况下起作用。我将在下面发布屏幕截图和我的代码。
日期未排序。

enter image description here

NotificationFragment.java

public class NotificationFragment extends Fragment {
        prepareNotification1();
        sortDate();
        return v;
    }

       private void prepareNotification1() {
            FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
            String userID = user.getUid();

  mRef.child("customers").child(userID).child("Notification").addChildEventListener(new ChildEventListener() {
            @Override
            public void onChildAdded(DataSnapshot dataSnapshot, String s) {
                    Notification menu = dataSnapshot.getValue(Notification.class);
                    notificationList.add(menu);
                mAdapter.notifyDataSetChanged();
            }
 });
    }

    public void sortDate() {
        Collections.sort(notificationList, new Comparator<Notification>() {
            @Override
            public int compare(Notification lhs, Notification rhs) {
                return lhs.getDate().compareTo(rhs.getDate());
            }
        });
        mAdapter = new NotificationAdapter(getContext(), notificationList);
        mRecyclerView.setAdapter(mAdapter);
    }
}

MyFirebaseMessagingService.java

public class MyFirebaseMessagingService extends FirebaseMessagingService {
@Override
    public void onMessageReceived(RemoteMessage remoteMessage) {
        Calendar cal = Calendar.getInstance();

        String currentDateTimeString = DateFormat.getDateInstance().format(new Date());

        SimpleDateFormat df = new SimpleDateFormat("hh:mm a");
        String currentTime = df.format(cal.getTime());

        String notificationTime = currentDateTimeString + " at " + currentTime;

        Notification newNotification = new Notification(remoteMessage.getData().get("body"), notificationTime);
        mRef.child("customers").child(userID).child("Notification").push().setValue(newNotification);
}

Notification.java

public class Notification {
    private String message;
    private String date;


    public Notification(){
    }

    public Notification(String message, String date){
        this.message = message;
        this.date = date;
    }

    public String getDate() {
        return date;
    }

    public void setDate(String date) {
        this.date = date;
    }

    public String getMessage() {
        return message;
    }

    public void setMessage(String message) {
        this.message = message;
    }
}

欢迎来到 Stack Overflow!寻求调试帮助的问题(“为什么这段代码不起作用?”)必须在问题本身中包含所需的行为、具体问题或错误以及重现它所需的最短代码。没有明确问题陈述的问题对其他读者没有用处。请参阅:如何创建一个最小、完整和可验证的示例。 - Joe C
getDate() 方法返回的是字符串还是日期格式? - Usman Rana
@UsmanRana 字符串格式。每次收到通知时,我都将其存储为 Firebase 中的字符串。 - arsenallavigne
1
我不了解Firebase,但是假设它与其他数据库有相似之处,那么它一定有一个日期类型。请使用此类型存储您的日期。 - Tim Biegeleisen
发布你的 Notification.java。 - akhilesh0707
显示剩余3条评论
6个回答

11

解析日期后进行排序。

Collections.sort(notificationList, new Comparator<Notification>() {
            DateFormat f = new SimpleDateFormat("dd/MM/yyyy '@'hh:mm a");
            @Override
            public int compare(Notification lhs, Notification rhs) {
                try {
                    return f.parse(lhs.getDate()).compareTo(f.parse(rhs.getDate()));
                } catch (ParseException e) {
                    throw new IllegalArgumentException(e);
                }
            }
        })

如果您的日期格式不同,请相应地编写DateFormat


2
不知道为什么这个答案有任何赞。对我来说它很好用。谢谢Ritesh。 - Hardik Joshi

5
考虑将通知中的日期存储为long(Unix时间)或Date(如果您使用Java 8支持,则为LocalDateTime),并在将其显示到UI时仅将其格式化为字符串。

1
哦,谢谢,我明白了。我将它作为字符串存储在我的“通知”中。 - arsenallavigne

2

按升序和降序对ArrayList进行日期排序

在我的答案中,我将使用名为debtsArrayList的债务ArrayList。本答案将展示如何按日期对带有对象的ArrayList进行升序降序排序。

排序比较器类

首先创建一个SortComparator类来保存按升序降序对日期进行排序的函数。

public class SortComparator {

    /**
     * Class to sort list by Date
     */
    public static class SortBy_Date {

        /**
         * Class to sort list by Date in ascending order
         */
        public static class Ascending implements Comparator<JB_Debts> {

            @Override
            public int compare(JB_Debts jbDebts1, JB_Debts jbDebts2) {

                // Create DateFormat
                DateFormat dateFormat = DateFormat.getDateInstance(
                        DateFormat.FULL, Locale.ENGLISH);

                // Catch Parse errors
                try {

                    // Parse dates
                    Date date1 = dateFormat.parse(jbDebts1.getDate());
                    Date date2 = dateFormat.parse(jbDebts2.getDate());

                    // Check if dates are null
                    if ((date1 != null) && (date2 != null)) {

                        // Ascending
                        return (date1.getTime() > date2.getTime() ? 1 : -1);

                    } else {

                        return 0; // Return 0 to leave it at current index
                    }
                } catch (Exception exception) {

                    exception.printStackTrace();
                }

                return 0;
            }
        }

        /**
         * Class to sort list by Date in descending order
         */
        public static class Descending implements Comparator<JB_Debts> {

            @Override
            public int compare(JB_Debts jbDebts1, JB_Debts jbDebts2) {

                // Create DateFormat
                DateFormat dateFormat = DateFormat.getDateInstance(
                        DateFormat.FULL, Locale.ENGLISH);

                // Catch Parse and NullPointerExceptions
                try {

                    // Parse dates
                    Date date1 = dateFormat.parse(jbDebts1.getDate());
                    Date date2 = dateFormat.parse(jbDebts2.getDate());

                    // Check if dates are null
                    if ((date1 != null) && (date2 != null)) {

                        // Descending
                        return (date1.getTime() > date2.getTime() ? -1 : 1);

                    } else {

                        return 0; // Return 0 to leave it at current index
                    }
                } catch (Exception exception) {

                    exception.printStackTrace();
                }

                return 0;
            }
        }
    }
}

在我的例子中,我使用一个带有对象的ArrayListArrayList<JB_Debts>,其中JB_Debts是我的Java bean类,具有getter和setter方法。
    public class JB_Debts {

    private String date; // Our date string

    /**
     * Default constructor
     */
    public JB_Debts2() {
    }

    /**
     * Function to get date
     */
    public String getDate() {

        return date;
    }

    /**
     * Function to set date
     *
     * @param date - Date
     */
    public void setDate(String date) {

        this.date = date;
    }
}

使用集合类

接下来,我们将使用Java集合类来对ArrayList<JB_Debts>中的对象按照日期升序和降序排序。

// Create ArrayList
ArrayList<JB_Debts> debtsArrayList = new ArrayList();

Collections.sort(debtsArrayList,
            new SortComparator.SortBy_Date.Ascending());

Collections.sort(debtsArrayList,
            new SortComparator.SortBy_Date.Descending());

注意

请注意,我将日期存储为字符串形式的ArrayList。为了对它们进行排序,我按以下方式解析了字符串:

// Create DateFormat with Locale
DateFormat dateFormat = DateFormat.getDateInstance(
                DateFormat.FULL, Locale.ENGLISH);

// Create DateFormat without Locale
DateFormat dateFormat = DateFormat.getDateInstance(
                DateFormat.FULL);

您可以将DateFormat.FULL替换为您选择的日期格式,例如"dd/MM/yyyy hh:mm a",然后会显示如下内容:
// Create DateFormat with Locale
DateFormat dateFormat = new SimpleDateFormat(
            "dd/MM/yyyy hh:mm a", Locale.ENGLISH);

// Create DateFormat without Locale
DateFormat dateFormat = new SimpleDateFormat(
            "dd/MM/yyyy hh:mm a");

我希望这可以帮助到你


2
您可以将日期时间字符串解析为 LocalDateTime ,然后执行自然排序。
使用 Stream
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("d MMM u 'at' h:m a", Locale.UK);
        
        Stream.of(
                    "10 Jul 2017 at 10:59 pm",
                    "10 Jul 2017 at 10:59 pm",
                    "11 Jul 2017 at 11:15 pm",
                    "9 Jul 2017 at 11:15 pm"
                )
                .map(s -> LocalDateTime.parse(s, dtf))
                .sorted()
                .forEach(dt -> System.out.println(dtf.format(dt)));
    }
}

输出:

9 Jul 2017 at 11:15 pm
10 Jul 2017 at 10:59 pm
10 Jul 2017 at 10:59 pm
11 Jul 2017 at 11:15 pm

非流式解决方案:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        final DateTimeFormatter dtf = DateTimeFormatter.ofPattern("d MMM u 'at' h:m a", Locale.UK);
        List<LocalDateTime> listLdt = new ArrayList<>();
        
        List<String> listDtStr = 
                Arrays.asList(
                                "10 Jul 2017 at 10:59 pm",
                                "10 Jul 2017 at 10:59 pm",
                                "11 Jul 2017 at 11:15 pm",
                                "9 Jul 2017 at 11:15 pm"
                            );
        
        // Add the strings, parsed into LocalDateTime, to listLdt
        for(String s: listDtStr) {
            listLdt.add(LocalDateTime.parse(s, dtf));
        }
        
        // Sort listLdt
        Collections.sort(listLdt);
        
        // Display
        for(LocalDateTime ldt: listLdt) {
            System.out.println(ldt.format(dtf));
        }
    }
}

输出:

9 Jul 2017 at 11:15 pm
10 Jul 2017 at 10:59 pm
10 Jul 2017 at 10:59 pm
11 Jul 2017 at 11:15 pm

了解更多关于现代日期时间 API 的内容,请访问Trail: Date Time

使用传统日期时间 API:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Locale;

public class Main {
    public static void main(String[] args) throws ParseException {
        final SimpleDateFormat sdf = new SimpleDateFormat("d MMM u 'at' h:m a", Locale.UK);
        List<Date> listDate = new ArrayList<>();
        
        List<String> listDtStr = 
                Arrays.asList(
                                "10 Jul 2017 at 10:59 pm",
                                "10 Jul 2017 at 10:59 pm",
                                "11 Jul 2017 at 11:15 pm",
                                "9 Jul 2017 at 11:15 pm"
                            );
        
        // Add the strings, parsed into LocalDateTime, to listDate
        for(String s: listDtStr) {
            listDate.add(sdf.parse(s));
        }
        
        // Sort listDate
        Collections.sort(listDate);
        
        // Display
        for(Date date: listDate) {
            System.out.println(sdf.format(date));
        }
    }
}

输出:

9 Jul 4 at 11:15 pm
10 Jul 5 at 10:59 pm
10 Jul 5 at 10:59 pm
11 Jul 6 at 11:15 pm

注意:Java.util日期时间API及其格式化API——SimpleDateFormat已经过时且容易出错。建议完全停止使用它们,并转向现代日期时间API*

* 如果出于任何原因,您必须坚持使用Java 6或Java 7,则可以使用ThreeTen-Backport,该工具将大多数java.time功能回溯到Java 6和7。如果您正在为Android项目工作,并且您的Android API级别仍不符合Java-8,请检查通过解糖可用的Java 8+ API如何在Android项目中使用ThreeTenABP


1
据我了解,Notification.getDate() 返回字符串值。因此,请使用:
public static Date toDate(String value) throws ParseException {
    DateFormat format = new SimpleDateFormat("d MMMM yyyy 'at' HH:mm'am'", Locale.ENGLISH);
    return format.parse(value);
}

使用这种方法从您的字符串中获取日期。只需获取两个日期并使用Date.compareTo方法。

date1 = toDate(lhs.getDate());
date2 = toDate(rhs.getDate());
date1.compareTo(date2);

0

在通知模型中,不要像以下代码一样设置日期:

String notificationTime = currentDateTimeString + " at " + currentTime;

你可以将时间保存为System.currentTimeinMillis();,在显示时再按照以下方式解析为日期。

DateFormat f = new SimpleDateFormat("dd/MM/yyyy hh:mm a");
f.parse(timeStamp);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接