按 Java 中字符串中的 2 个子字符串排序

Sorting by 2 substrings in a string in Java

我正在尝试根据字符串的两个组成部分以相反的顺序排列字符串列表(在 Java 中),第一个是月份(需要按时间倒序排列)和第二个是字符串开头的整数值(不代表日期,因此可能超过 31)。例如:

List<String> dates = List.of("13 Dec", "44 Jun", "12 Dec", "103 Aug", "22 Sep", "23 Sep");

一旦订购应该return:

[13 Dec, 12 Dec, 23 Sep, 22 Sep, 103 Aug, 44 June]

谁能给我举个例子说明如何做到这一点?谢谢

你需要

  1. 拆分字符串
String[] split=string.split(" ");
  1. 测试第二个子串是否相同
split1[1].equals(split2[1])
  1. 如果相同,比较天数
Integer.parseInt(split1[0])<Integer.parseInt(split2[0]);

如果不是,则使用数组将月份名称与月份名称或类似名称进行比较。

private static final String[] MONTHS={"Jan","Feb",...};
private int getMonthNumeric(String abbr){
    for(int i=0;i<MONTHS.length();i++){
        if(abbr.equals(MONTHS[i]){
            return i;
        }
    }
    return -1;
}
//in your comparator
getMonthNumeric(split1[1])<getMonthNumeric(split1[1])

一个简单的比较器(忽略边缘情况)可能如下所示(使用 lambda):

(a,b)->{
    String[] split1=a.split(" ");
    String[] split2=b.split(" ");
    if(split1[1].equals(split2[1])){
        return Integer.parseInt(split1[0])-Integer.parseInt(split2[0]);
    }else{
        return getMonthNumeric(split1[1])-getMonthNumeric(split1[1]);
    }
}

您对列表进行排序的代码可能如下所示:

private static final String[] MONTHS={"Jan","Feb",...};
private int getMonthNumeric(String abbr){
    for(int i=0;i<MONTHS.length();i++){
        if(abbr.equals(MONTHS[i]){
            return i;
        }
    }
    return -1;
}
//Where you want to sort the date:
Collections.sort(dates,(a,b)->{
        String[] split1=a.split(" ");
        String[] split2=b.split(" ");
        if(split1[1].equals(split2[1])){
            return Integer.parseInt(split1[0])-Integer.parseInt(split2[0]);
        }else{
            return getMonthNumeric(split1[1])-getMonthNumeric(split1[1]);
        }
    }
);

为#sorted 流方法提供您自己的比较器。 下面的示例比较了月份索引。如果它们相等(差为 0),则比较数字。 检查 doc about sorted.

import java.text.DateFormatSymbols;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class Test {

    /* [Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec, ] */
    static String[] shortMonths = new DateFormatSymbols().getShortMonths();
    static int getMonthIndex(String word) {
        return Arrays.asList(shortMonths).indexOf(word.substring(0, Math.min(word.length(), 3)));
    }

    public static void main(String[] args) {
        List<String> dates = Arrays.asList("13 Dec", "44 June", "12 Dec", "103 Aug", "22 Sep", "23 Sep");

        dates = dates.stream().sorted((s1, s2) -> {
            String[] a1 = s1.split(" ");
            String[] a2 = s2.split(" ");
            int comp = getMonthIndex(a2[1]) - (getMonthIndex(a1[1]));
            return comp != 0 ? comp : a2[0].compareTo(a1[0]);
        }).collect(Collectors.toList());

        System.out.println(dates);
    }

}

将产生 [13 Dec, 12 Dec, 23 Sep, 22 Sep, 103 Aug, 44 June].

这是一种方法。它使用一些 java.time 功能来获取当月的值。

List<String> dates = new ArrayList<>(List.of("13 Dec",
        "44 June", "12 Dec", "103 Aug", "22 Sep", "23 Sep"));

首先,使用 DateTimeFormatter 获取等效的整数月份。这避免了创建外部数据结构来保存月份。

Function<String, Integer> monNum = month -> DateTimeFormatter
        .ofPattern("MMM").parse(month)
        .get(ChronoField.MONTH_OF_YEAR);

然后构造一个比较器来比较字符串,先按月,然后按数字,两者倒序。

Comparator<String> comp =
    Comparator.comparing((String str) -> str.split("\s+"),
        Comparator.comparingInt((String[] a) -> monNum.apply(a[1]))
            .thenComparing(a -> Integer.parseInt(a[0])))
         .reversed();
        
dates.sort(comp);
System.out.println(dates);

版画

[13 Dec, 12 Dec, 23 Sep, 22 Sep, 103 Aug, 44 June]