简体   繁体   中英

Java - How to sort an ArrayList of Strings with seasons and years?

I have an unsorted ArrayList of Strings of seasons and years like the following:

["Summer 2020", "Autumn 2018", "Spring 2019", "Autumn 2019", "Winter 2018", "Summer 2018", "Winter 2020", "Spring 2018"]

The correct sorting of this list is the following:

["Winter 2018", "Spring 2018", "Summer 2018", "Autumn 2018", "Spring 2019", "Autumn 2019", "Winter 2020", "Summer 2020"]

How can I achieve this order? The order of seasons in a year is like Winter 2021, Spring 2021, Summer 2021, Autumn 2021, and all the seasons for every year will not necessarily exist in the list.

You'll need to implement a custom Comparator that sorts by the year first and then by the seasons. An enum can be used to specify the order of the seasons easily.

private static class SeasonComparator implements Comparator<String> {
    
    private enum Season {
        WINTER, SPRING, SUMMER, AUTUMN
    }

    @Override
    public int compare(String s1, String s2) {
        String[] arr1 = s1.split(" ");
        String[] arr2 = s2.split(" ");
        
        int year1 = Integer.parseInt(arr1[1]);
        int year2 = Integer.parseInt(arr2[1]);
        
        if (year1 != year2) {
            return year1 - year2;
        } else {
            Season season1 = Season.valueOf(arr1[0].toUpperCase());
            Season season2 = Season.valueOf(arr2[0].toUpperCase());
            return season1.ordinal() - season2.ordinal();
        }
    }
}

public static void main(String[] args) {
    List<String> seasons = new ArrayList<>(Arrays.asList("Summer 2020", "Autumn 2018",
            "Spring 2019", "Autumn 2019", "Winter 2018", "Summer 2018", "Winter 2020", "Spring 2018"));

    System.out.println("Unordered list:");
    System.out.println(seasons);
    
    seasons.sort(new SeasonComparator());
    
    System.out.println("Sorted list:");
    System.out.println(seasons);
}

Output

Unordered list:
[Summer 2020, Autumn 2018, Spring 2019, Autumn 2019, Winter 2018, Summer 2018, Winter 2020, Spring 2018]

Sorted list:
[Winter 2018, Spring 2018, Summer 2018, Autumn 2018, Spring 2019, Autumn 2019, Winter 2020, Summer 2020]

You need to write own comparator for such strings. I suggest you to use arrow function for it. Also, to sort seasons you need to give them some priority, I would use Map<String, Integer> for it.

Try this code:

public static void main(String[] args) {
    Map<String, Integer> seasonsPriority = new HashMap<>();
    seasonsPriority.put("Winter", 1);
    seasonsPriority.put("Spring", 2);
    seasonsPriority.put("Summer", 3);
    seasonsPriority.put("Autumn", 4);

    ArrayList<String> seasons = new ArrayList<>();
    seasons.add("Summer 2020");
    seasons.add("Autumn 2018");
    seasons.add("Spring 2019");
    seasons.add("Autumn 2019");
    seasons.add("Winter 2018");
    seasons.add("Summer 2018");
    seasons.add("Winter 2020");
    seasons.add("Spring 2018");


    seasons.sort((x, y) -> {
        int firstYear = Integer.parseInt(x.split(" ")[1]);
        int secondYear = Integer.parseInt(y.split(" ")[1]);

        if(firstYear < secondYear) {
            return -1;
        }

        if(firstYear > secondYear) {
            return 1;
        }

        String firstSeason = x.split(" ")[0];
        String secondSeason = y.split(" ")[0];

        return Integer.compare(seasonsPriority.get(firstSeason), seasonsPriority.get(secondSeason));
    });

    System.out.println(seasons);
}

Output:

[Winter 2018, Spring 2018, Summer 2018, Autumn 2018, Spring 2019, Autumn 2019, Winter 2020, Summer 2020]

Consider writing a custom Comparator to perform sorting with custom logic.

public static void main(String[] args) {
    List<String> list = Arrays.asList("Summer 2020", "Autumn 2018", "Spring 2019", "Autumn 2019", "Winter 2018", "Summer 2018", "Winter 2020", "Spring 2018");

    List<String> listOfSeasonsInAscendingOrder = Arrays.asList("Winter", "Spring", "Summer", "Autumn");

    Collections.sort(list, new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            String firstStringSplit[] = o1.split(" ");
            String season1 = firstStringSplit[0];
            int year1 = Integer.valueOf(firstStringSplit[1]);

            String secondStringSplit[] = o2.split(" ");
            String season2 = secondStringSplit[0];
            int year2 = Integer.valueOf(secondStringSplit[1]);

            if (year1 != year2) {
                return year1 < year2 ? -1 : 1;
            }

            int indexOfSeason1 = listOfSeasonsInAscendingOrder.indexOf(season1);
            int indexOfSeason2 = listOfSeasonsInAscendingOrder.indexOf(season2);

            return indexOfSeason1 == indexOfSeason2 ? 0 : indexOfSeason1 < indexOfSeason2 ? -1 : 1;
        }
    });

    System.out.println("Sorted List = " + list);
}

Output of the above code is :-

Sorted List = [Winter 2018, Spring 2018, Summer 2018, Autumn 2018, Spring 2019, Autumn 2019, Winter 2020, Summer 2020]

Try this.

static final Map<String, Integer> SEASON_ORDER = Map.of(
    "Winter", 0, "Spring", 1, "Summer", 2, "Autumn", 3);

public static void main(String[] args) {
    List<String> list = new ArrayList<>(List.of(
        "Summer 2020", "Autumn 2018", "Spring 2019", "Autumn 2019",
        "Winter 2018", "Summer 2018", "Winter 2020", "Spring 2018"));
    list.sort(Comparator.comparing(s -> {
        String[] a = s.split("\\s+");
        return a[1] + SEASON_ORDER.get(a[0]);
    }));
    System.out.println(list);
}

output:

[Winter 2018, Spring 2018, Summer 2018, Autumn 2018, Spring 2019, Autumn 2019, Winter 2020, Summer 2020]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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