简体   繁体   English

如何对包含年份的月份列表进行排序

[英]How to sort a list of months with years

I have a list of months with years such as: [12-2014,11-2012,5-2014,8-2012] and I have to sort them with the most recent on top (or the latest date on top) eg.我有一个包含年份的月份列表,例如: [12-2014,11-2012,5-2014,8-2012]我必须将它们排序为最近的(或最晚的日期)例如。 [12-2014,5-2014,11-2012,8-2012] . [12-2014,5-2014,11-2012,8-2012] .
Does anybody have any idea on how to do this in Java efficiently?有人知道如何在Java中有效地执行此操作吗?

EDIT:编辑:
The class YearMonth is not available, I'm on Java 7 class YearMonth不可用,我在Java 7

Java-8 onwards Java-8起

Create a Stream out of the list, map each String of the Stream into YearMonth using a DateTimeFormatter , sort the Stream using Comparator#reverseOrder , map each YearMonth element of the Stream into the String using the same DateTimeFormatter and finally, collect the Stream into a List<String> .使用dateTimeFormatter在DateTimeFormatter中创建StreamString使用dateTimeFormatter,将Stream列入YearMonthStream DateTimeFormatter Comparator#reverseOrder ,将String分组YearMonth element StreamList<String>

Demo:演示:

import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;

public class Main {
    public static void main(String args[]) {
        List<String> list = List.of("12-2014", "11-2012", "5-2014", "8-2012");
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("M-uuuu", Locale.ENGLISH);
        List<String> sorted = 
                list.stream()
                    .map(s -> YearMonth.parse(s, dtf))
                    .sorted(Comparator.reverseOrder())
                    .map(ym -> dtf.format(ym))
                    .collect(Collectors.toList());

        // Display the list
        System.out.println(sorted);
    }
}

Output: Output:

[12-2014, 5-2014, 11-2012, 8-2012]

ONLINE DEMO在线演示

Learn more about the modern Date-Time API * from Trail: Date Time .Trail: Date Time了解更多关于现代日期时间 API *的信息。


* If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring . * 如果您正在为 Android 项目工作,并且您的 Android API 级别仍然不符合 Java-8,请检查Java 8+ APIs available through desugaring Note that Android 8.0 Oreo already provides support for java.time .请注意,Android 8.0 Oreo 已经提供了java.time的支持

尝试使用比较器或类似产品,并通过拆分来检查月份。

use a custom String comparator. 使用自定义的字符串比较器。 http://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html http://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html

I can write the code out if you would like. 如果您愿意,我可以将代码写出来。

Here is some sudo code for now: 现在是一些sudo代码:

Arrays.sort(yearList, new Comparator<String>{

    //get the year and month of o1 and o2 as ints

    //if the years are different then return the difference of the years

    //if the years are the same then return the difference of the months

}

Try something like (untested): 尝试类似(未试用)的方法:

private final static DateTimeFormatter YEAR_MONTH_FORMATTER = 
    DateTimeFormatter.ofPattern("MM-yyyy");

...

List<String> yearMonthStrings = ...;
List<YearMont> yearMonthList = yearMonthStrings.stream()
    .map(s -> YearMonth.parse(s, YEAR_MONTH_FORMATTER)
    .sorted()
    .collect(Collectors.toList());

// or
List<YearMont> yearMonthList = yearMonthStrings.stream()
    .map(s -> YearMonth.parse(s, YEAR_MONTH_FORMATTER)
    .sorted(Collections.reverseOrder())
    .collect(Collectors.toList());

Since you are using Java 7 you can take advantage of the Date class as well as the Comparator interface and its usage in a Set object like the treeSet for instance. 由于您使用的是Java 7,因此可以利用Date类以及Comparator接口及其在Set对象(例如treeSet)中的用法。

Here is an implementation of the Comparator interface to compare two dates 这是比较器接口的一个实现,用于比较两个日期

public class MonthYearComparator implements Comparator<Date> {

    public int compare(Date o1, Date o2) {
        // TODO Auto-generated method stub
        return -1*o1.compareTo(o2);
    }

}

And then here is how we could use it. 然后这就是我们如何使用它。 First I will use a SimpleDateFormat class to parse your strings as dates. 首先,我将使用SimpleDateFormat类将您的字符串解析为日期。 To do that I need to complete them and make them look as formated date strings. 为此,我需要完成它们并使它们看起来像格式化的日期字符串。 Since the day is irrelevant for the comparison I could take any day like "01". 由于这一天与比较无关紧要,因此我可以选择“ 01”之类的任何一天。

Once I have turned them into Date objects I will add them to a instance of a TreeSet which is provided with a Comparator and they will automatically be sorted as I add them. 将它们转换为Date对象后,我会将它们添加到Comparator随附的TreeSet实例中,并且在添加它们时会自动对其进行排序。

Then I can substract the part of the date that I need which will be a substring(3) of my date object after being formated as a string. 然后,我可以减去需要的日期部分,将其格式化为字符串后将成为日期对象的substring(3)。

Here is the code (for demo sake I used the same datas that you provided as example): 这是代码(为演示起见,我使用了您提供的与示例相同的数据):

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

public class MonthYearIssue {

    private List<String> listOfMonthYears = new ArrayList<String>();
    private static final String USED_DATE_FORMAT = "dd-MM-yyyy";
    SimpleDateFormat formatter = new SimpleDateFormat(USED_DATE_FORMAT);

    public void setUpMonthYearsList() {
        listOfMonthYears.add("12-2014");
        listOfMonthYears.add("11-2012");
        listOfMonthYears.add("5-2014");
        listOfMonthYears.add("8-2012");
    }

    public Date parseToDate(String monthYearString) throws ParseException {
        return formatter.parse("01-" + monthYearString);
    }

    public List<String> doSort() throws ParseException {

        List<String> result = new ArrayList<String>();
        Set<Date> dates = new TreeSet<Date>(new MonthYearComparator());

        for (String monthYearStr: listOfMonthYears) {
            dates.add(parseToDate(monthYearStr));

        }

        for (Object d: dates.toArray()) {

            result.add(formatter.format((Date)d).substring(3));
        }

        System.out.println(result);
        return result;

    }

    public static void main(String[] args) throws ParseException {
        MonthYearIssue issueSolver = new MonthYearIssue();
        issueSolver.setUpMonthYearsList();
        issueSolver.doSort();
    }

}

Here is the result: 结果如下:

[12-2014, 05-2014, 11-2012, 08-2012] [12-2014、05-2014、11-2012、08-2012]

Date类是可比较的,因此您可以为数组中的每个String创建Date的实例,然后可以对它们进行排序

tl;dr tl;博士

Never use the terrible legacy date-time classes such as Date & Calendar .永远不要使用糟糕的遗留日期时间类,例如Date & Calendar

Always use their replacement, the modern java.time classes defined in JSR 310. Most of that functionality has been back-ported to Java 6 & 7 in ThreeTen-Backport .始终使用它们的替代品,即 JSR 310 中定义的现代java.time类。大部分功能已在ThreeTen- Backport 中向后移植到 Java 6 和 7。

List < String > inputs = Arrays.asList( "12-2014" , "11-2012" , "5-2014" , "8-2012" );
DateTimeFormatter f = DateTimeFormatter.ofPattern( "M-uuuu" );

List < YearMonth > yearMonths = new ArrayList <>( inputs.size() );
for ( String input : inputs )
{
    try { yearMonths.add( YearMonth.parse( input , f ) ); } catch ( DateTimeException e ) { System.out.println( "ERROR - Faulty input: " + input ); }
}

Collections.sort( yearMonths , Collections.reverseOrder() );

Back-port java.time to Java 7后端口java.time到 Java 7

You said you are restricted to Java 7. While not built-in, most of the modern java.time functionality is available to you.你说你仅限于 Java 7. 虽然不是内置的,但大多数现代java.time功能都可供您使用。 Add the ThreeTen-Backport library to your project.ThreeTen-Backport库添加到您的项目中。

If using Maven, add this to your POM:如果使用 Maven,请将其添加到您的 POM 中:

<dependency>
  <groupId>org.threeten</groupId>
  <artifactId>threetenbp</artifactId>
  <version>1.5.1</version>
</dependency>

The legacy date-time classes such as Date , Calendar , SimpleDateFormat are terribly flawed in design. DateCalendarSimpleDateFormat等遗留日期时间类在设计上存在严重缺陷。 They really are such an awful mess that adding a library to your project is well-worth the chore.它们真的是一团糟,以至于向您的项目添加一个库是值得的。

DateTimeFormatter

Set up your inputs.设置你的输入。

By the way, your input text is using a custom format of M-YYYY.顺便说一下,您的输入文本使用的是自定义格式 M-YYYY。 I suggest you educate the publisher of your data about the ISO 8601 standard for formatting date-time values exchanged textually.我建议您向您的数据发布者介绍ISO 8601标准,以格式化文本交换的日期时间值。 The standard format for a year-month is YYYY-MM.年-月的标准格式是 YYYY-MM。

Define a formatter to match your non-standard inputs.定义格式化程序以匹配您的非标准输入。

List < String > inputs = Arrays.asList( "12-2014" , "11-2012" , "5-2014" , "8-2012" );
DateTimeFormatter f = DateTimeFormatter.ofPattern( "M-uuuu" );

YearMonth

Parse your inputs a YearMonth objects, adding each a new List .解析您输入的YearMonth对象,为每个对象添加一个新的List

If an input might be faulty, you can trap for DateTimeException to detect and handle such a problem.如果输入可能有问题,您可以捕获DateTimeException来检测和处理此类问题。

List < YearMonth > yearMonths = new ArrayList <>( inputs.size() );
for ( String input : inputs )
{
    try { yearMonths.add( YearMonth.parse( input , f ) ); } catch ( DateTimeException e ) { System.out.println( "ERROR - Faulty input: " + input ); }
}

Collections.sort && Collections.reverseOrder Collections.sort && Collections.reverseOrder

Sort your list.对列表进行排序。 You want the latest first, so pass the optional second argument, a Comparator to reverse the sorting on natural-order.你想要最新的第一个,所以传递可选的第二个参数,一个Comparator来反转自然顺序的排序。

Collections.sort( yearMonths , Collections.reverseOrder() );

Report our new list.报告我们的新名单。

System.out.println( "yearMonths = " + yearMonths );

Example code示例代码

Pull all that code together.将所有代码放在一起。

package work.basil;

import org.threeten.bp.DateTimeException;
import org.threeten.bp.YearMonth;
import org.threeten.bp.format.DateTimeFormatter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

/**
 * Example parsing year-month values using ThreeTen-Backport library
 * giving us most of the Java 8+ *java.time* functionality.
 **/
public class App
{
    public static void main ( String[] args )
    {
        List < String > inputs = Arrays.asList( "12-2014" , "11-2012" , "5-2014" , "8-2012" );
        DateTimeFormatter f = DateTimeFormatter.ofPattern( "M-uuuu" );

        List < YearMonth > yearMonths = new ArrayList <>( inputs.size() );
        for ( String input : inputs )
        {
            try { yearMonths.add( YearMonth.parse( input , f ) ); } catch ( DateTimeException e ) { System.out.println( "ERROR - Faulty input: " + input ); }
        }

        Collections.sort( yearMonths , Collections.reverseOrder() );

        System.out.println( "yearMonths = " + yearMonths );
    }
}

When run.运行时。

yearMonths = [2014-12, 2014-05, 2012-11, 2012-08]年月 = [2014-12、2014-05、2012-11、2012-08]


By the way, here is a Maven POM for this app, using the latest versions of various parts.顺便说一句,这里有一个 Maven 这个应用程序的 POM,使用了各个部分的最新版本。

<?xml version="1.0" encoding="UTF-8"?>

<project xmlns = "http://maven.apache.org/POM/4.0.0"
         xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>work.basil</groupId>
    <artifactId>J7</artifactId>
    <version>1.0-SNAPSHOT</version>

    <name>J7</name>
    <!-- FIXME change it to the project's website -->
    <url>http://www.example.com</url>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.7</maven.compiler.source>
        <maven.compiler.target>1.7</maven.compiler.target>

    </properties>

    <dependencies>

        <!-- https://mvnrepository.com/artifact/junit/junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.2</version>
            <scope>test</scope>
        </dependency>

        <!--https://www.threeten.org/threetenbp/-->
        <dependency>
            <groupId>org.threeten</groupId>
            <artifactId>threetenbp</artifactId>
            <version>1.5.1</version>
        </dependency>


    </dependencies>

    <build>
        <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) -->
            <plugins>
                <!-- clean lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#clean_Lifecycle -->
                <plugin>
                    <artifactId>maven-clean-plugin</artifactId>
                    <version>3.1.0</version>
                </plugin>
                <!-- default lifecycle, jar packaging: see https://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_jar_packaging -->
                <plugin>
                    <artifactId>maven-resources-plugin</artifactId>
                    <version>3.2.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>3.8.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-surefire-plugin</artifactId>
                    <version>3.0.0-M5</version>
                </plugin>
                <plugin>
                    <artifactId>maven-jar-plugin</artifactId>
                    <version>3.2.0</version>
                </plugin>
                <plugin>
                    <artifactId>maven-install-plugin</artifactId>
                    <version>3.0.0-M1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-deploy-plugin</artifactId>
                    <version>3.0.0-M1</version>
                </plugin>
                <!-- site lifecycle, see https://maven.apache.org/ref/current/maven-core/lifecycles.html#site_Lifecycle -->
                <plugin>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>3.9.1</version>
                </plugin>
                <plugin>
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <version>3.1.2</version>
                </plugin>
            </plugins>
        </pluginManagement>
    </build>
</project>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM