【发布时间】:2010-10-01 05:23:21
【问题描述】:
我有一个文件名数组,需要按文件名的扩展名对该数组进行排序。有没有简单的方法可以做到这一点?
【问题讨论】:
标签: java arrays file sorting filenames
我有一个文件名数组,需要按文件名的扩展名对该数组进行排序。有没有简单的方法可以做到这一点?
【问题讨论】:
标签: java arrays file sorting filenames
如果我没记错的话, Arrays.sort(...) 需要一个 Comparator 来进行排序。您可以提供一个查看字符串扩展部分的实现。
【讨论】:
您可以实现自定义的Comparator 字符串。使其按'.' 的最后一个索引之后的子字符串对它们进行排序。然后将比较器和您的数组传入
Arrays.sort(stringArray, yourComparator);
// An implementation of the compare method
public int compare(String o1, String o2) {
return o1.substring(o1.lastIndexOf('.')).compareTo(o2.substring(o2.lastIndexOf('.'));
}
【讨论】:
创建一个比较器并比较字符串扩展名。下面一起来看看
http://java.sun.com/j2se/1.4.2/docs/api/java/util/Comparator.html
然后将您的字符串列表传递给 Arrays.sort(List, Comparator)
【讨论】:
创建您自己的Comparator,将字符串视为文件名并根据扩展名进行比较。然后将 Arrays.sort 与 Comparator 参数一起使用。
【讨论】:
Arrays.sort(filenames, new Comparator<String>() {
@Override
public int compare(String s1, String s2) {
// the +1 is to avoid including the '.' in the extension and to avoid exceptions
// EDIT:
// We first need to make sure that either both files or neither file
// has an extension (otherwise we'll end up comparing the extension of one
// to the start of the other, or else throwing an exception)
final int s1Dot = s1.lastIndexOf('.');
final int s2Dot = s2.lastIndexOf('.');
if ((s1Dot == -1) == (s2Dot == -1)) { // both or neither
s1 = s1.substring(s1Dot + 1);
s2 = s2.substring(s2Dot + 1);
return s1.compareTo(s2);
} else if (s1Dot == -1) { // only s2 has an extension, so s1 goes first
return -1;
} else { // only s1 has an extension, so s1 goes second
return 1;
}
}
});
为了完整起见:java.util.Arrays 和 java.util.Comparator。
【讨论】:
如果您只想按扩展名对文件进行分组而不关心实际的字母顺序,您可以使用这个:
我认为当文件名没有“。”时,您可以做的最简单的事情也适用。就是把名字倒过来比较一下。
Arrays.sort(ary, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
String r1 = new StringBuffer(o1).reverse().toString();
String r2 = new StringBuffer(o2).reverse().toString();
return r1.compareTo(r2);
}
});
可惜java的字符串连reverse()都没有。
【讨论】:
比较器通常很难完全正确,并且必须为每次比较生成比较键,对于大多数排序算法来说,这意味着 O(n log n)。另一种方法是为您需要排序的每个项目创建(键,值)对,将它们放在 TreeMap 中,然后根据键对这些值进行排序。
例如
import java.util.Arrays;
import java.util.TreeMap;
public class Bar {
public static void main(String[] args) {
TreeMap<String, String> m2 = new TreeMap<String, String>();
for (String string : Arrays.asList(new String[] { "#3", "#2", "#1" })) {
String key = string.substring(string.length() - 1);
String value = string;
m2.put(key, value);
}
System.out.println(m2.values());
}
}
打印出来
[#1、#2、#3]您应该能够轻松地根据您的问题调整密钥计算。
每个条目只计算一次键,因此 O(n) - (但排序仍然是 O(n log n))。如果密钥计算很昂贵或 n 很大,这可能是相当可衡量的。
【讨论】:
String DELIMETER = File.separator + ".";
List<String> orginalList = new CopyOnWriteArrayList<>(Arrays.asList(listOfFileNames));
Set<String> setOfuniqueExtension = new TreeSet<>();
for (String item : listOfFileNames) {
if (item.contains(".")) {
String[] split = item.split(DELIMETER);
String temp = "." + split[split.length - 1];
setOfuniqueExtension.add(temp);
}
}
List<String> finalListOfAllFiles = new LinkedList<>();
setOfuniqueExtension.stream().forEach((s1) -> {
for (int i = 0; i < orginalList.size(); i++) {
if (orginalList.get(i).contains(s1)) {
finalListOfAllFiles.add(orginalList.get(i));
orginalList.remove(orginalList.get(i));
i--;
}
}
});
orginalList.stream().filter((s1) -> (!finalListOfAllFiles.contains(s1))).forEach((s1) -> {
finalListOfAllFiles.add(s1);
});
return finalListOfAllFiles;
【讨论】: