Java 比较器<;文件>;至于;“目录优先”;秩序
我被难住了。。。假设我有这个目录树:Java 比较器<;文件>;至于;“目录优先”;秩序,java,file,comparator,Java,File,Comparator,我被难住了。。。假设我有这个目录树: {someRoot}/ {someRoot}/bar/ {someRoot}/bar/file1.txt {someRoot}/foo/ {someRoot}/foo/baz/ {someRoot}/foo/baz/file3.txt {someRoot}/foo/abracadabra.txt {someRoot}/foo/file2.txt {someRoot}/aardvark.txt {someRoot}/food.txt {someRoot}/ze
{someRoot}/
{someRoot}/bar/
{someRoot}/bar/file1.txt
{someRoot}/foo/
{someRoot}/foo/baz/
{someRoot}/foo/baz/file3.txt
{someRoot}/foo/abracadabra.txt
{someRoot}/foo/file2.txt
{someRoot}/aardvark.txt
{someRoot}/food.txt
{someRoot}/zebra.txt
你会注意到顺序。称之为订单1。在每个阶段,目录都排在文件之前。(注意:bar/file1.txt
位于foo
之前,因此在全局范围内,并非所有目录都位于所有文件之前。)
如果我枚举这个目录树,然后递归地枚举子目录,我将得到下面的列表
,排序为order2
{someRoot}/
{someRoot}/aardvark.txt
{someRoot}/bar/
{someRoot}/foo/
{someRoot}/food.txt
{someRoot}/zebra.txt
{someRoot}/bar/file1.txt
{someRoot}/foo/abracadabra.txt
{someRoot}/foo/baz/
{someRoot}/foo/file2.txt
{someRoot}/foo/baz/file3.txt
如果我创建简单的比较器
:
但是我不想要这个排序(它有问题:注意food.txt
位于目录foo
及其子项之间),我想要order1。我如何编写一个比较器来获得它呢?编辑
您必须比较第一级的基本目录和第二级的文件名
import java.io.File;
import java.io.IOException;
import java.util.Comparator;
public class FileComparator implements Comparator<File> {
@Override
public int compare(File o1, File o2) {
int pathCompare = this.getPath(o1).compareTo(this.getPath(o2));
if (pathCompare != 0) {
return subPathCompare;
} else {
if (o1.isDirectory() && !o2.isDirectory()) {
return -1;
} else if (!o1.isDirectory() && o2.isDirectory()) {
return 1;
} else {
return o1.compareTo(o2);
}
}
}
//maybe there is a better way to speparete path and file name, but it works
private String getPath(File file) {
if (file.isFile()) {
return file.getParent().toLowerCase();
} else {
return file.getPath().toLowerCase();
}
}
}
结果不是第1种情况,而是另一种情况,其中所有目录都是第一项,文件是最后一项:
\dir1\
\dir2\
\dir3\
\dir4\
\dir1\file1\
\dir1\file2\
\dir2\file1\
\dir2\file2\
因此,我的解决方案是首先检查两个比较文件是否属于同一目录
- 如果它们不属于同一个目录,则通过该目录对它们进行比较李>
- 如果子目录属于同一目录,则子目录“排序”在“普通文件”之前
比较器fc=新比较器(){
@覆盖公共整数比较(文件o1、文件o2){
布尔值isFirstDirectory=o1.isDirectory();
布尔值isSecondDirectory=o2.isDirectory();
如果(!isFirstDirectory&!isSecondDirectory){
返回o1。与(o2)相比;
}else if(isFirstDirectory&!isSecondDirectory){
返回(int)1;
}else if(isSecondDirectory&!isFirstDirectory){
返回-1;
}否则{
返回o1。与(o2)相比;
}
}
};
此递归地获取您喜欢的已排序文件树:
public static void main(String[] args) {
List<File> files = getFileTree(new File("."));
for (File f : files)
System.out.println(f);
}
private static List<File> getFileTree(File file) {
List<File> files = new LinkedList<File>();
files.add(file);
if (file.isDirectory()) {
File[] current = file.listFiles();
Arrays.sort(current, new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
if (o1.isDirectory())
return o2.isDirectory() ? o1.compareTo(o2) : -1;
else if (o2.isDirectory())
return 1;
return o1.compareTo(o2);
}
});
for (File f : current)
files.addAll(getFileTree(f));
}
return files;
}
publicstaticvoidmain(字符串[]args){
列表文件=getFileTree(新文件(“.”);
用于(文件f:文件)
系统输出打印ln(f);
}
私有静态列表getFileTree(文件){
列表文件=新建LinkedList();
文件。添加(文件);
if(file.isDirectory()){
File[]current=File.listFiles();
sort(当前,新的比较器(){
@凌驾
公共整数比较(文件o1、文件o2){
if(o1.isDirectory())
返回o2.isDirectory()?o1.compareTo(o2):-1;
else if(o2.isDirectory())
返回1;
返回o1。与(o2)相比;
}
});
用于(文件f:当前)
addAll(getFileTree(f));
}
归还文件;
}
我确实找到了一种实现我想要的伪相反的方法(文件后的目录,没有检查文件和目录名位于根级别的边缘情况)
…不,把它转换成我想要的不是小事,因为我使用的是目录的字典排序,它将不同级别的目录排序与同一级别的目录排序结合起来
static class FileDirectoryPriorityComparator implements Comparator<File>
{
@Override public int compare(File f1, File f2) {
if (f1.isDirectory())
{
if (f2.isDirectory())
{
return f1.compareTo(f2);
}
else
{
return compareDirFile(f1, f2);
}
}
else
{
if (f2.isDirectory())
{
return -compareDirFile(f2, f1);
}
// f1 and f2 are both files
else
{
return compareFiles(f1, f2);
}
}
}
private int compareDirFile(File dir, File file) {
/*
* If dir compares differently to file's parent, use that ordering.
* Otherwise, dir comes before file.
*/
File fparent = file.getParentFile();
if (fparent == null)
return -1;
int i = dir.compareTo(fparent);
if (i != 0)
return i;
return -1;
}
private int compareFiles(File f1, File f2) {
/*
* If f1's parent compares differently to f2's parent, use that ordering.
* Otherwise use default ordering.
*/
File fp1 = f1.getParentFile();
File fp2 = f2.getParentFile();
if (fp1 == null)
{
if (fp2 != null)
{
return 1;
}
}
else
{
if (fp2 == null)
{
return -1;
}
else
{
int i = fp1.compareTo(fp2);
if (i != 0)
return i;
}
}
return f1.compareTo(f2);
}
}
静态类FileDirectoryPriorityComparator实现Comparator
{
@覆盖公共整数比较(文件f1、文件f2){
if(f1.isDirectory())
{
if(f2.isDirectory())
{
返回f1.compareTo(f2);
}
其他的
{
返回比较文件(f1,f2);
}
}
其他的
{
if(f2.isDirectory())
{
返回-比较文件(f2,f1);
}
//f1和f2都是文件
其他的
{
返回比较文件(f1、f2);
}
}
}
私有int比较文件(文件目录,文件文件){
/*
*如果dir与文件的父级比较不同,则使用该顺序。
*否则,dir位于file之前。
*/
File fparent=File.getParentFile();
如果(fparent==null)
返回-1;
int i=直接比较(fparent);
如果(i!=0)
返回i;
返回-1;
}
专用整数比较文件(文件f1、文件f2){
/*
*如果f1的父级与f2的父级比较不同,则使用该顺序。
*否则,使用默认顺序。
*/
文件fp1=f1.getParentFile();
文件fp2=f2.getParentFile();
如果(fp1==null)
{
如果(fp2!=null)
{
返回1;
}
}
其他的
{
如果(fp2==null)
{
返回-1;
}
其他的
{
int i=fp1。与(fp2)相比;
如果(i!=0)
返回i;
}
}
返回f1.compareTo(f2);
}
}
这在我的测试中有效
new Comparator<File>() {
@Override
public int compare(File first, File second) {
if (first.isDirectory() && second.isDirectory())
return first.compareTo(second);
if (first.isDirectory())
return this.compareToFile(first, second);
if (second.isDirectory())
return -(this.compareToFile(second, first));
return this.compareFiles(first, second);
}
private int compareFiles(File first, File second) {
File firstParentFile = first.getParentFile();
File secondParentFile = second.getParentFile();
if (isSubDir(firstParentFile, secondParentFile))
return -1;
if (isSubDir(secondParentFile, firstParentFile))
return 1;
return first.compareTo(second);
}
private int compareToFile(File directory, File file) {
File fileParent = file.getParentFile();
if (directory.equals(fileParent))
return -1;
if (isSubDir(directory, fileParent))
return -1;
return directory.compareTo(file);
}
private boolean isSubDir(File directory, File subDir) {
for (File parentDir = directory.getParentFile(); parentDir != null; parentDir = parentDir.getParentFile()) {
if (subDir.equals(parentDir)) {
return true;
}
}
return false;
}
新比较器(){
@凌驾
公共int比较(文件第一,文件第二){
if(第一个.isDirectory()&第二个.isDirectory())
首先返回。比较(第二);
if(first.isDirectory())
返回此.compareToFile(第一个,第二个);
if(second.isDirectory())
返回-(this.compareToFile(第二个,第一个));
返回此.compareFiles(第一个,第二个);
}
私有int比较文件(文件第一,文件第二){
File firstParentFile=first.getParentFile();
File secondParentFile=second.getParentFile();
if(isSubDir(第一个父文件,第二个父文件))
返回-1;
if(isSubDir(secondParentFile,firstParentFile))
返回1;
冷杉
Comparator<File> fc = new Comparator<File>(){
@Override public int compare(File o1, File o2) {
boolean isFirstDirectory = o1.isDirectory();
boolean isSecondDirectory = o2.isDirectory();
if(!isFirstDirectory && !isSecondDirectory) {
return o1.compareTo(o2);
} else if (isFirstDirectory && !isSecondDirectory){
return (int) 1;
} else if(isSecondDirectory && !isFirstDirectory) {
return -1;
} else {
return o1.compareTo(o2);
}
}
};
public static void main(String[] args) {
List<File> files = getFileTree(new File("."));
for (File f : files)
System.out.println(f);
}
private static List<File> getFileTree(File file) {
List<File> files = new LinkedList<File>();
files.add(file);
if (file.isDirectory()) {
File[] current = file.listFiles();
Arrays.sort(current, new Comparator<File>() {
@Override
public int compare(File o1, File o2) {
if (o1.isDirectory())
return o2.isDirectory() ? o1.compareTo(o2) : -1;
else if (o2.isDirectory())
return 1;
return o1.compareTo(o2);
}
});
for (File f : current)
files.addAll(getFileTree(f));
}
return files;
}
static class FileDirectoryPriorityComparator implements Comparator<File>
{
@Override public int compare(File f1, File f2) {
if (f1.isDirectory())
{
if (f2.isDirectory())
{
return f1.compareTo(f2);
}
else
{
return compareDirFile(f1, f2);
}
}
else
{
if (f2.isDirectory())
{
return -compareDirFile(f2, f1);
}
// f1 and f2 are both files
else
{
return compareFiles(f1, f2);
}
}
}
private int compareDirFile(File dir, File file) {
/*
* If dir compares differently to file's parent, use that ordering.
* Otherwise, dir comes before file.
*/
File fparent = file.getParentFile();
if (fparent == null)
return -1;
int i = dir.compareTo(fparent);
if (i != 0)
return i;
return -1;
}
private int compareFiles(File f1, File f2) {
/*
* If f1's parent compares differently to f2's parent, use that ordering.
* Otherwise use default ordering.
*/
File fp1 = f1.getParentFile();
File fp2 = f2.getParentFile();
if (fp1 == null)
{
if (fp2 != null)
{
return 1;
}
}
else
{
if (fp2 == null)
{
return -1;
}
else
{
int i = fp1.compareTo(fp2);
if (i != 0)
return i;
}
}
return f1.compareTo(f2);
}
}
new Comparator<File>() {
@Override
public int compare(File first, File second) {
if (first.isDirectory() && second.isDirectory())
return first.compareTo(second);
if (first.isDirectory())
return this.compareToFile(first, second);
if (second.isDirectory())
return -(this.compareToFile(second, first));
return this.compareFiles(first, second);
}
private int compareFiles(File first, File second) {
File firstParentFile = first.getParentFile();
File secondParentFile = second.getParentFile();
if (isSubDir(firstParentFile, secondParentFile))
return -1;
if (isSubDir(secondParentFile, firstParentFile))
return 1;
return first.compareTo(second);
}
private int compareToFile(File directory, File file) {
File fileParent = file.getParentFile();
if (directory.equals(fileParent))
return -1;
if (isSubDir(directory, fileParent))
return -1;
return directory.compareTo(file);
}
private boolean isSubDir(File directory, File subDir) {
for (File parentDir = directory.getParentFile(); parentDir != null; parentDir = parentDir.getParentFile()) {
if (subDir.equals(parentDir)) {
return true;
}
}
return false;
}
public class DirectoryBeforeFileComparator implements Comparator<File> {
@Override
public int compare(File o1, File o2) {
if (o1.isDirectory() && !o2.isDirectory()) {
// directory before non-directory.
return -1;
}
if (!o1.isDirectory() && o2.isDirectory()) {
// non-directory after directory
return 1;
}
// compare two pathnames lexicographically
return o1.compareTo(o2);
}
}