【发布时间】:2015-04-24 20:25:18
【问题描述】:
我看到过类似的其他问题,但无法将任何信息调整到我的代码中。要么是因为它不是特定于我的问题,要么是我无法理解答案。所以,我希望用我的具体代码问“如何”。如果需要更多,请告诉我。
我有各种名称格式为“20140214-ddEventBlahBlah02.jpg”和“20150302-ddPsBlagBlag2”的文件(全部为 jpg)。
我有一个自定义比较器正在使用,它以 Windows 操作系统的方式对事物进行排序......即 02、2、003、4、4b、4c、10 等。而不是计算机的排序方式,这被搞砸了。一切都很好,除了我现在想使用字符串中的 2 个标准对这些字符串进行排序。
1) 日期(在开头)。即20150302 2) "-" 之后的文件名的其余部分,即 ddPsBlagBlag2
我目前正在将比较器用于以相反顺序显示这些文件的项目。它们根据最近添加的内容进行显示。即 20150302 在 20140214 之前显示。这很好。但我希望这些文件在按日期倒序排序后,以正常的 Windows 操作系统升序(而不是倒序)按名称显示。
代码:
Collections.sort(file, new Comparator<File>()
{
private final Comparator<String> NATURAL_SORT = new WindowsExplorerComparator();
@Override
public int compare(File o1, File o2)
{
return NATURAL_SORT.compare(o1.getName(), o2.getName());
}
});
Collections.reverse(file);
上面的代码获取文件名的 ArayList 并将其发送到自定义 WindowsExplorerComparator 类。排序后,在 ArrayList 上调用 Collections.reverse()。
代码:
class WindowsExplorerComparator implements Comparator<String>
{
private static final Pattern splitPattern = Pattern.compile("\\d\\.|\\s");
@Override
public int compare(String str1, String str2) {
Iterator<String> i1 = splitStringPreserveDelimiter(str1).iterator();
Iterator<String> i2 = splitStringPreserveDelimiter(str2).iterator();
while (true)
{
//Til here all is equal.
if (!i1.hasNext() && !i2.hasNext())
{
return 0;
}
//first has no more parts -> comes first
if (!i1.hasNext() && i2.hasNext())
{
return -1;
}
//first has more parts than i2 -> comes after
if (i1.hasNext() && !i2.hasNext())
{
return 1;
}
String data1 = i1.next();
String data2 = i2.next();
int result;
try
{
//If both datas are numbers, then compare numbers
result = Long.compare(Long.valueOf(data1), Long.valueOf(data2));
//If numbers are equal than longer comes first
if (result == 0)
{
result = -Integer.compare(data1.length(), data2.length());
}
}
catch (NumberFormatException ex)
{
//compare text case insensitive
result = data1.compareToIgnoreCase(data2);
}
if (result != 0) {
return result;
}
}
}
private List<String> splitStringPreserveDelimiter(String str) {
Matcher matcher = splitPattern.matcher(str);
List<String> list = new ArrayList<String>();
int pos = 0;
while (matcher.find()) {
list.add(str.substring(pos, matcher.start()));
list.add(matcher.group());
pos = matcher.end();
}
list.add(str.substring(pos));
return list;
}
}
上面的代码是用于对 ArrayList 进行排序的自定义 WindowsExplorerComperator 类。
所以,我希望 ArrayList 在排序后(并且日期排序反转)后的样子是:
20150424-ssEventBlagV002.jpg
20150323-ssEventBlagV2.jpg
20150323-ssEventBlagV3.jpg
20150323-ssEventBlagV10.jpg
20141201-ssEventZoolander.jpg
20141102-ssEventApple1.jpg
如您所见,首先按日期排序(并反转),然后按字符串名称的其余部分升序排序。
这可能吗?请告诉我这是一个简单的解决方法。
【问题讨论】:
-
感谢大家。最后,我使用了 pathfinderelite 的代码,并进行了一些更改。我所有的更改都在 pathfinderelites 答案下的 cmets 中。再次感谢。