[英]Compare dates from a String in list
我在繼續時遇到問題。 我有一個列表,在每個 position 中都包含一個字符串(在該短語的末尾有一個日期)
例子:
I am new here 20/8/2019
我想以這種方式對列表進行排序:在 position 零中,我想要包含最舊日期和以下位置的短語,日期將更新。
我嘗試使用 SimpleDateFormat 和 Date,但我不知道該怎么做。
String variable, variable2, c;
int d = 0;
for(int i = 0; i < lista.size(); i++) {
for(int j = 1; j <lista.size(); j++) {
variable = lista.get(i);
variable2 = lista.get(j);
c = compareDates(variable, variable2);
lista.add(d,c);
d++;
}
}
private static Date compareDates(String variable, String variable2) throws ParseException {
SimpleDateFormat formateador = new SimpleDateFormat("dd/MM/yyyy");
String var = formateador.format(variable);
String var2 = formateador.format(variable2);
if (var.before(var2)) {
return var;
} else {
if (var2.before(var1)) {
} else {
}
return null;
}
}
線程“主”java.lang.Error 中的異常:未解決的編譯問題:類型不匹配:無法從日期轉換為字符串
at Ejercicio.ClaseMain.leerDes(ClaseMain.java:124)
第 124 行:c = compareDates(variable, variable2);
視覺示例:列表中的每個 position 都有一個帶有日期的短語:
問題是,我讀了一個 .txt 文件,其中有幾行。 文件內容:
塞維利亞將自己保留給Apoel,並沒有光彩奪冠; 體育 Julen Lopetegui 徹底改變了 11 人,旨在將 rest 給予常客,這並沒有阻止他的團隊在比賽中獲得第二次勝利 2019 年 10 月 10 日
班克斯的一幅英國議會被黑猩猩占領的畫作,以 1100 萬歐元成交) 10/2019
我用一段時間來讀取文件行並將每一行保存在列表中的每個 position 處,我想對列表進行排序。 舊日期 ---> 最近日期。
請不要使用舊的日期庫,而是使用java.time
API,所以如果您使用的是 Java 8,您的解決方案可以是:
String[] strs = {"20/10/2019", "5/2/2019", "12/12/2019",
"1/8/2019", "25/12/2019", "2/1/2019", "6/9/2019"};
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/M/uuuu");
List<LocalDate> collect = Stream.of(strs)
.map(s -> LocalDate.parse(s, formatter)) // convert your strings to dates
.sorted() // sort the dates
.collect(Collectors.toList()); // collect the result in a collection
Output
[2019-01-02, 2019-02-05, 2019-08-01, 2019-09-06, 2019-10-20, 2019-12-12, 2019-12-25]
考慮到List
中的所有字符串格式相同,並且在拆分后的第四個索引處具有date
,如下所示
List<String> list = new ArrayList<>();
list.add("I am new here 20/11/2019 ");
list.add("I am Deadpool here 20/7/2019 ");
list.add("I am IronMan here 20/6/2019 ");
現在使用比較器根據LocalDate
對List
進行排序
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/M/yyyy");
list.sort(Comparator.comparing(str->LocalDate.parse(str.split(" ")[4],formatter)));
System.out.println(list); //I am IronMan here 20/6/2019 , I am Deadpool here 20/7/2019 , I am new here 20/11/2019 ]
我的解決方案是:
List<String> lista = List.of(
"Sevilla reserves himself to Apoel … sportyou 10/10/2019",
"I am new here 20/8/2019",
"A painting by Banksy … 19/10/2019");
List<String> sortedList = lista.stream()
.map(s -> new Object() {
String theString = s;
LocalDate date = extractDate(s);
})
.sorted(Comparator.comparing(obj -> obj.date))
.map(obj -> obj.theString)
.collect(Collectors.toList());
sortedList.forEach(System.out::println);
Output 這是:
I am new here 20/8/2019 Sevilla reserves himself to Apoel … sportyou 10/10/2019 A painting by Banksy … 19/10/2019
我使用的extractDate
方法是:
private static Pattern datePattern = Pattern.compile("\\d{1,2}/\\d{1,2}/\\d{4}$");
private static DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("d/M/u");
private static LocalDate extractDate(String fullString) {
Matcher m = datePattern.matcher(fullString);
if (m.find()) {
String dateString = m.group();
return LocalDate.parse(dateString, dateFormatter);
} else {
throw new IllegalArgumentException("String doesn’t end with a date: " + fullString);
}
}
為了對字符串進行有效排序——只有在有很多字符串時才重要——我提取了尾隨日期並為每個字符串只解析一次(而不是每次比較)。 我正在解析LocalDate
並使用它們進行排序。 為了在排序后取出原始字符串,我將String
和LocalDate
都放入 object 中,然后對這些對象進行排序。 我可以以這種方式使用Object
的匿名子類,這可能會讓一些人感到驚訝,但它工作得很好。
我建議您不要使用SimpleDateFormat
和Date
。 這些類設計不佳且早已過時,尤其是前者,尤其是出了名的麻煩。 相反,我使用LocalDate
和DateTimeFormatter
,兩者都來自 java.time,現代 Java 日期和時間 API。
Java 內置了不錯的分揀設施。 如果編寫自己的排序算法是為了練習,那是一個很好的練習。 坦率地說,在你的排序工作之前,你仍然有辦法 go 。 您可能想閱讀排序算法,在 WWW 上也有很多文章。 對於生產代碼,您應該依賴庫方法。
鏈接: Oracle 教程:日期時間解釋如何使用 java.time。
像“20/8/2019”這樣的日期與“dd/MM/yyyy”模式不匹配。 正確的格式應該是“20/08/2019”。 排序的最短解決方案是
list.sort(Comparator.comparing(
source -> LocalDate.parse(source, DateTimeFormatter.ofPattern("dd/MM/yyyy"))));
發生錯誤是因為在compareDates
方法返回類型是Date
而返回是String
。
現在來到解決方案,如果目的只是從短語中提取排序日期,這應該可行。 但是查看 OP 中的代碼,我感覺您正在嘗試對按日期排序的短語列表進行冒泡排序,這也可以按照相同的方式實現。
重要的部分是通過Regex
提取日期。
代碼:
List<LocalDate> ld = new ArrayList<LocalDate>();
for(int i = 0; i < lista.size(); i++){
ld.add(getDateFromString(lista.get(i)));
}
//sorting the list of dates extracted
ld = ld.stream().sorted().collect(Collectors.toCollection(ArrayList::new));
private static LocalDate getDateFromString(String str){
LocalDate d;
//looks for pattern dd/mm/yyyy in the passed string
Matcher m = Pattern.compile("(\\d{1,2}/\\d{1,2}/\\d{4})").matcher(str);
if(m.find()) {
String match = m.group(1);
d = LocalDate.parse(match, DateTimeFormatter.ofPattern("d/MM/yyyy"));
}
return d;
}
注意:這里假設每個短語都有一個日期字符串,格式為dd/mm/yyyy
簡單地說,如果您不知道日期字符串的格式,就不可能將字符串轉換為日期。 “10/11/12”是 10 月 11 日還是 12 年 11 月 10 日,還是 10 年 11 月 12 日? 請參閱如何在不知道格式的情況下將字符串轉換為日期? .
在您的文本示例中,最后一個日期只是“10/2019”,而您使用“20/8/2019”作為另一個示例,因此您似乎有多種可能的格式。 如果您可以限制可能性,則可能會找到最佳匹配。
如果您可以使用正則表達式提取該日期作為文本末尾的數字序列和正斜杠(請參閱ambianBeing的答案),那么您可以嘗試使用從最嚴格到最寬松的可能格式解析此字符串,捕獲'DateTimeParseException' 異常並在第一次成功解析時停止。 如果沒有成功,請標記它,以便您確定要修復的內容 - 文本、添加新格式或更好的正則表達式。
使用上面的示例,您可以從格式模式開始
dd/MM/yyyy
dd/M/yyyy
MM/yyyy
如果一切都失敗了,請使用 null 日期來標記條目。
如果將其放入返回日期的方法中,則可以使用 stream 解決方案按照其他幾個人的建議對列表進行排序。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.