如何使用季节和年份对字符串的 ArrayList 进行排序?
How to sort an ArrayList of Strings with seasons and years?
我有一个未排序的季节和年份字符串数组列表,如下所示:
["Summer 2020", "Autumn 2018", "Spring 2019", "Autumn 2019", "Winter 2018", "Summer 2018", "Winter 2020", "Spring 2018"]
此列表的正确排序如下:
["Winter 2018", "Spring 2018", "Summer 2018", "Autumn 2018", "Spring 2019", "Autumn 2019", "Winter 2020", "Summer 2020"]
我怎样才能达到这个顺序?一年中的季节顺序如Winter 2021, Spring 2021, Summer 2021, Autumn 2021,不一定每年的所有季节都在列表中。
您需要为此类字符串编写自己的 comparator
。我建议你使用 arrow
函数。另外,要对季节进行排序,您需要给它们一些优先级,我会使用 Map<String, Integer>
。
试试这个代码:
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);
}
输出:
[Winter 2018, Spring 2018, Summer 2018, Autumn 2018, Spring 2019, Autumn 2019, Winter 2020, Summer 2020]
您需要实施自定义 Comparator
,先按年份排序,然后再按季节排序。 enum
可用于轻松指定季节的顺序。
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);
}
输出
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]
考虑编写自定义比较器以使用自定义逻辑执行排序。
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);
}
以上代码的输出是:-
Sorted List = [Winter 2018, Spring 2018, Summer 2018, Autumn 2018, Spring 2019, Autumn 2019, Winter 2020, Summer 2020]
试试这个。
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);
}
输出:
[Winter 2018, Spring 2018, Summer 2018, Autumn 2018, Spring 2019, Autumn 2019, Winter 2020, Summer 2020]
前面的回答都是在comparator函数中进行字符串拆分解析。这工作得很好,但可能会导致大规模的性能问题 - 拆分和解析可能是相对昂贵的操作,并且在排序时比较器需要平均检查每个元素不止一次。让比较器为自然排序正确的每个元素计算一个代码,并使用映射记住这些代码,以避免对每个元素执行多次这些操作,可能会提高性能:
public class Scratch {
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.sort(new SeasonYearComparator());
System.out.println(list);
}
private enum Season {
Winter, Spring, Summer, Autumn;
}
private static class SeasonYearComparator implements Comparator<String> {
private final Map<String, String> codes = new HashMap<>();
@Override
public int compare(String s1, String s2) {
String code1 = codes.computeIfAbsent(s1, this::computeCode);
String code2 = codes.computeIfAbsent(s2, this::computeCode);
return code1.compareTo(code2);
}
private String computeCode(String seasonYear) {
String[] parts = seasonYear.split(" ");
return parts[1] + Season.valueOf(parts[0]).ordinal();
}
}
}
我有一个未排序的季节和年份字符串数组列表,如下所示:
["Summer 2020", "Autumn 2018", "Spring 2019", "Autumn 2019", "Winter 2018", "Summer 2018", "Winter 2020", "Spring 2018"]
此列表的正确排序如下:
["Winter 2018", "Spring 2018", "Summer 2018", "Autumn 2018", "Spring 2019", "Autumn 2019", "Winter 2020", "Summer 2020"]
我怎样才能达到这个顺序?一年中的季节顺序如Winter 2021, Spring 2021, Summer 2021, Autumn 2021,不一定每年的所有季节都在列表中。
您需要为此类字符串编写自己的 comparator
。我建议你使用 arrow
函数。另外,要对季节进行排序,您需要给它们一些优先级,我会使用 Map<String, Integer>
。
试试这个代码:
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);
}
输出:
[Winter 2018, Spring 2018, Summer 2018, Autumn 2018, Spring 2019, Autumn 2019, Winter 2020, Summer 2020]
您需要实施自定义 Comparator
,先按年份排序,然后再按季节排序。 enum
可用于轻松指定季节的顺序。
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);
}
输出
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]
考虑编写自定义比较器以使用自定义逻辑执行排序。
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);
}
以上代码的输出是:-
Sorted List = [Winter 2018, Spring 2018, Summer 2018, Autumn 2018, Spring 2019, Autumn 2019, Winter 2020, Summer 2020]
试试这个。
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);
}
输出:
[Winter 2018, Spring 2018, Summer 2018, Autumn 2018, Spring 2019, Autumn 2019, Winter 2020, Summer 2020]
前面的回答都是在comparator函数中进行字符串拆分解析。这工作得很好,但可能会导致大规模的性能问题 - 拆分和解析可能是相对昂贵的操作,并且在排序时比较器需要平均检查每个元素不止一次。让比较器为自然排序正确的每个元素计算一个代码,并使用映射记住这些代码,以避免对每个元素执行多次这些操作,可能会提高性能:
public class Scratch {
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.sort(new SeasonYearComparator());
System.out.println(list);
}
private enum Season {
Winter, Spring, Summer, Autumn;
}
private static class SeasonYearComparator implements Comparator<String> {
private final Map<String, String> codes = new HashMap<>();
@Override
public int compare(String s1, String s2) {
String code1 = codes.computeIfAbsent(s1, this::computeCode);
String code2 = codes.computeIfAbsent(s2, this::computeCode);
return code1.compareTo(code2);
}
private String computeCode(String seasonYear) {
String[] parts = seasonYear.split(" ");
return parts[1] + Season.valueOf(parts[0]).ordinal();
}
}
}