0

可能重复:
按日期对特殊字符串的数组列表进行排序

我有一个从文件中读取的字符串数组列表,每个字符串的第一部分是一个日期,例如:12/01/2012。当我使用 Collections.sort(); 它在一年内从最旧到最新对其进行排序,但是当它到达 2013 年 1 月 1 日时,它会将其放在最旧的列表顶部。我怎样才能让它使用年份作为排序的一部分?我尝试使用日期,但它也是如此。每个字符串都有很多我想保留的信息,只需从头开始排序。我认为没有必要发布代码,因为它正在工作,而我遇到的所有问题只是排序。我在这里搜索了一段时间并尝试了一些不同的排序选项无济于事。所以我一定很困惑或忘记了什么。如果有人对如何在开头对带有日期的字符串进行排序有任何想法,请提供帮助!谢谢!

示例字符串:“2012 年 12 月 1 日 34023843 项目编号”

4

4 回答 4

1

如果字符串总是相同的格式,你可以实现一个自定义比较器并使用 Collections.sort(list,comparator) 这个比较器将首先检查年,然后是月,然后是日。

或者,(最好的解决方案 ahma),您可以重新设计具有多个字段(和日期)的对象列表,并使用日期实现比较器。直接使用字符串永远不会保存(例如,此处使用字符串比较器,您将无法使用其他日期格式)

于 2013-01-01T23:36:55.607 回答
1

您当前正在使用字符串排序进行排序。这意味着“01/01/2013”​​排在“12/31/2012”之前,因为“0”小于“1”。

您可以使用自定义比较器来使用不同的逻辑。在您的比较器中,您将:

  1. 拆分字符串以获取日期
  2. 使用 SimpleDateFormat 将字段 0 转换为日期
  3. 然后在你的两个日期打电话比较
于 2013-01-01T23:37:46.537 回答
1

您需要一个自定义比较器。以自然顺序比较字符串(即使用Stringimplements的事实Comparable<String>)将给出您看到的结果,因为0低于1,所以这是预期的。

这是一个示例类,它可以做你想做的事,但请注意,它假定所有日期的格式都正确(如果日期不正确,该parse()方法会DateFormat抛出未选中IllegalArgumentException的内容):

public final class MyComparator
    implements Comparator<String>
{
    // Date parsing
    // Note: SimpleDateFormat is not thread-safe, if possible use Joda Time instead
    private static final DateFormat fmt = new SimpleDateFormat("dd/MM/YYYY");

    private static final Comparator<String> INSTANCE = new MyComparator();

    private MyComparator()
    {
    }

    public static Comparator<String> getInstance()
    {
        return INSTANCE;
    }

    @Override
    public int compare(String o1, String o2)
    {
        // Grab dates
        String s1 = o1.subString(0, 10);
        Date d1 = fmt.parse(s1);
        String s2 = o2.subString(0, 10);
        Date d2 = fmt.parse(s2);

        // Date implements Comparable<Date>, so we can use that...
        int ret = d1.compareTo(d2);

        // If dates are equal, compare the rest of the strings instead.
        return ret != 0 ? ret : o1.subString(10).compareTo(o2.subString(10));
    }
}

然后你可以使用Collections.sort(theArray, MyComparator.getInstance());

于 2013-01-01T23:41:45.633 回答
0

@fge 的答案有效,但比较器必须多次拆分和转换字符串。事实上,对于典型的排序算法,这需要执行O(NlogN)多次,其中N是列表的长度。对于大型列表,该logN术语将很重要。

我的建议是创建一个自定义Line类来表示文件中的行。让构造函数将表示行的字符串解析为组件,解析日期组件并将所有相关组件保存在私有字段中。让自定义类实现Comparable<Line>,并实现compareTo(Line)按日期比较行的方法。

然后将文件内容表示为ArrayList<Line>而不是ArrayList<String>.

(有可能你无论如何都需要解析这些行......在它们被排序之后。所以这种方法只是在排序之前进行解析,并且只做一次。FWIW,“重复”问题的答案涵盖这也是:按日期对特殊字符串的数组列表进行排序

于 2013-01-02T00:06:06.687 回答