Java拡張子によるファイル名の文字列配列のソート
質問
ファイル名の配列があり、その配列をファイル名の拡張子でソートする必要があります。これを行う簡単な方法はありますか?
解決
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(...)はComparator <!> lt; <!> gt;を取ります。ソートの実行に使用します。文字列の拡張部分を調べる実装を提供できます。
カスタムコンパレータ文字列の。 '.'
の最後のインデックスの後の部分文字列で並べ替えます。次に、コンパレータと配列を
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('.'));
}
比較器は正確に取得するのが難しいことが多く、比較キーはすべての比較に対して生成する必要があります。ほとんどのソートアルゴリズムでは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]
キーの計算を問題に簡単に適合させることができるはずです。
これは、エントリごとに1回だけキーを計算するため、O(n)-(ただし、ソートは依然としてO(n log n)です)。キーの計算が高価であるか、nが大きい場合、これは非常に測定可能です。
コンパレータを作成し、文字列の拡張子を比較します。以下をご覧ください
http://java.sun .com / j2se / 1.4.2 / docs / api / java / util / Comparator.html
次に、文字列のリストをArrays.sort(List、Comparator)に渡します
独自のコンパレータ文字列をファイル名として扱い、拡張子に基づいてそれらを比較します。次に、 Arrays.sort を使用します。 Comparator引数。
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;
ファイルを拡張子でグループ化したいだけで、実際のアルファベット順を気にしない場合は、これを使用できます:
filennameに<!> quot;。<!> quot;がない場合にもできる最も簡単なことができると思います。名前を逆にして比較するだけです。
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()がないことも残念です。