[英]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.