555555555555555555555555555555555555
Java 真的这样慢吗???????

解决方案 »

  1.   

    是不是你每次都用 list 方法了?
    把 600 个文件名存在数组或是 List 里,再比较,应该会快一些。
      

  2.   

    嗬嗬,完全没有必要的,你可以把文件依次放入一个JList中,没时间,回来写
      

  3.   

    为了程序的灵活性,数据肯定时放在一个 List 中的了!!!但我使用的是 add 和 get 速度最快的 ArrayList ,这样的效率和直接使用数组的效率差距很小.至于多开线程,用处不太大, CPU 使用率已经到了 100%,再多开线程,可能效果也不大了!!把文件依次放入一个JList中,几百个上千文件,除了计算机,谁能慢慢的去找;里面相同的啊!!本来执行一次查找 30 秒,不算太多.
    但这样我这个程序就不能比较两个盘中是不是有多余的文件了
    一个盘可是有上万个文件啊,这样比较下去,一天也完不成啊!!!!!
      

  4.   

    现在有一个好的方法:我记得有一篇文章讲, java 为了效率,程序中所有的内容一样的字符串都是指向的同一个对象!!不过这话我再没有在其他地方找到证实!!要是真是这样就好了!!!
    比较字符串,只需要比较对象的地址就可以了,这个速度可就飞快了!!!!!谁能够证实一下!!!!!!!!
    谢谢!!!!!!
      

  5.   

    把它放入ListSet中,这个排序比较快,你只要比较一下相邻的是不是相等就行了,如果没有同名也就需要(n-1)次比较
      

  6.   

    另外,String是引用类型,每次都创建新对象,量大当然就慢了,你可以把文件名放入byte数组中,虽然数组也是引用类型,但是你不需要为每个文件名创建一个数组
      

  7.   

    File dir = new File("D:\\");
    String[] files = dir.list();
    HashSet set = new HashSet(600);
    for(int i=0; i<files.length; i++)
    {
        if(set.contains(files[i]))
            System.out.println("file exist:" + files[i]);
        else
            set.add(files[i]);
    }
      

  8.   

    File dir1 = new File("D:\\");
    File dir2 = new File("C:\\");HashSet set = new HashSet(600);String[] files1 = dir1.list();
    for(int i=0; i<files1.length; i++)
    {
        if(set.contains(files1[i]))
            System.out.println("file exist:" + files1[i]);
        else
            set.add(files1[i]);
    }String[] files2 = dir2.list();
    for(int i=0; i<files2.length; i++)
    {
        if(set.contains(files2[i]))
            System.out.println("file exist:" + files2[i]);
        else
            set.add(files2[i]);
    }
      

  9.   

    File dir1 = new File("C:\\WINNT\\system32");
    File dir2 = new File("C:\\WINNT");C:\WINNT\system32目录有2081个目录和文件
    C:\WINNT目录有188个目录和文件执行时间: 70毫秒
      

  10.   

    没那么慢吧
    我用最简单的遍历的结果:public class Test {
      static int COUNT = 0;
      public static void findFile(File dir, String filename) {
        File[] files = dir.listFiles();
        for (int i = 0; i < files.length; i++) {
          if (files[i].isDirectory()) {
            findFile(files[i], filename);
          } else {
            COUNT++;
            if (files[i].getName().equals(filename)) {
              System.out.println("Got it: " + files[i].getAbsolutePath());
            }
          }
        }
      }  public static void main(String[] args) {
        String NAME = "acpi.sys";
        File dir = new File("C:\\Windows");
        long time1 = System.currentTimeMillis();
        findFile(dir, NAME);
        long time2 = System.currentTimeMillis();
        System.out.println("Total time " + (time2 - time1));
        System.out.println("Total files " + COUNT);
      }
    }输出:Got it: C:\Windows\system32\drivers\acpi.sys
    Total time 750
    Total files 7056而且硬盘还是星钻的
      

  11.   

    windows的文件查找功能好像也挺慢的,java也无能为力吧
      

  12.   

    import java.util.Date;class StringCompareTest 
    {
    public static void main(String[] args) 
    {
            String str1 = "This is a very long string!99999999999999999999999999999999999999999999999999999999999999999999999999999";
            String str2 = "This is a very long string!999999999999999999999999999999999999999999999999999999999999999999999999999990";        System.out.println("Begin test...");
            System.out.println(System.currentTimeMillis() + "");
            System.out.println(new Date());        for (int i=0; i<100000000; i++)
            {
                str1.equals(str2);
            }
            System.out.println("End test.");
            System.out.println(System.currentTimeMillis() + "");
            System.out.println(new Date());
    }
    }试试这个测试程序,1亿次比较,看花多久?
    要知道两个字符串相同的部分是很长的,否则要快几十倍。
    用VC写同样的程序,一点也不会比java快!
      

  13.   

    谢谢各位了!!欢迎大家继续讨论!!!(我这个程序的功能:由用户指定一个目录,然后搜索这个目录中是否由多余的文件,这个多余的文件主要指相同的文件.当然这个相同是由一些用户自己定义的规则来判断的)首先我要澄清一些事情:
    1.列文件清单是非常快的,我自己使用的递归算法,列一个目录(包括子目录)里的文件,经测试,10000个文件全部列出来,并分别构建成 File 类放到一个 List中 ,需要的时间也就只有不到 2S 中的时间.2.程序的真正的性能瓶颈在比较上,我这个程序不是查找某一个文件,而是在一堆文件中查找"相同"的文件(这个相同是由一些用户自己定义的规则来判断的).所以比较的次数是几何增长的. 比如:1000 个文件,每个文件两两都要比较一次,共需比较 1000*500=500000 次.这个数字已经很大了,在我的 P4 上就需要 3-4 分钟了.要是文件数达到 10000 个,比较次数为 10000*5000 = 50000000,一共要 5000万次,这就得好几个钟头了. 要是文件总数达到 10万(谁的硬盘里没有 10 多万个文件),就是不可能完成的任务了.3.关于各位提到了排序,因为这个文件的列表是由具体的用户指定的,也就是具有不确定性.因此可以肯定,10000个文件以下,排序肯定比遍历来得慢.4.使用 Set 来实现(因为 Set 中的对象不能相同).但这是不能用的,不信大家可以试试,大家可创建两个内容相同的不同对象,一样可以添加到 Set 中,也就是说,Set 只会比较是不是同一个对象,而不会去比较对象的内容是不是相同.而且我这里的文件名的比较规则,也并不是要求一摸一样,规则可以用户自己定制.
      

  14.   

    同意cbhyk()的 观点
    支持楼主!!!
    开多个线程试试,
    主线程用于进行比较,
    其它的线程用于罗列目录,
    并放入容器。
      

  15.   

    楼主可能对Set有误解, 看看javadoc:
    public interface Set extends Collection
    A collection that contains no duplicate elements. More formally, sets contain no pair of elements e1 and e2 such that e1.equals(e2), and at most one null element.比较的规则不确定,自己实现equals方法就是了如果使用HashSet,则麻烦在于除了要覆盖equals方法, 还要根据用户定义的规则调整生成文件名的hasCode的算法, HashSet实际上调用HashMap的containsKey方法, 即首先是基于hashCode实现查找(缩小查找范围), 然后再调用equals比较.
      

  16.   

    import java.io.File;
    import java.util.HashMap;public class DuplicateFileCheck
    {
        private HashMap checkMap = new HashMap();
        private HashMap counterMap = new HashMap();    public void check(File dir, boolean recursive)
        {
            Counter counter = new Counter();
            counterMap.put(dir, counter);
            check(dir, counter, recursive);
        }    public void reset()
        {
            counterMap.clear();
            checkMap.clear();
        }    public int getFileCount(File dir)
        {
            Counter counter = (Counter) counterMap.get(dir);
            return counter.count;
        }    public int getDistinctCount()
        {
            return checkMap.size();
        }    private void check(File file, Counter counter, boolean recursive)
        {
            if(file.isDirectory())
                checkDir(file, counter, recursive);
            else
                checkFile(file, counter);
        }    private void checkDir(File dir, Counter counter, boolean recursive)
        {
            File[] files = dir.listFiles();
            for(int i=0; i<files.length; i++)
            {
                File file = files[i];
                if(file.isFile())
                {
                    checkFile(file, counter);
                }
                else
                {
                    if(recursive)
                    {
                        check(file, counter, recursive);
                    }
                }
            }
        }    private void checkFile(File file, Counter counter)
        {
            counter.count++;
            Object key = createCheckKey(file);
            File exist = (File) checkMap.get(key);
            if(exist != null)
            {
                System.out.println("file duplicate:" + file.getAbsolutePath() + " <--> " + exist.getAbsolutePath());
            }
            else
            {
                checkMap.put(key, file);
            }
        }    protected Object createCheckKey(File file)
        {
            return new CheckKey(file);
        }    private static class Counter
        {
            int count = 0;
        }    private static class CheckKey
        {
            private String filename;        public CheckKey(File file)
            {
                this.filename = file.getName();
            }        public boolean equals(Object obj)
            {
                CheckKey other = (CheckKey) obj;
                return filename.equals(other.filename);
            }        public int hashCode()
            {
                return filename.hashCode();
            }        public String toString()
            {
                return filename.toString();
            }
        }    public static void main(String[] args) throws Exception
        {
            File[] dirs = new File[]{
                new File("C:\\WINNT"),
                new File("D:\\temp"),
                new File("D:\\share")
            };        DuplicateFileCheck checker = new DuplicateFileCheck();
            boolean recursive = true; //是否包含子目录        long startTime = System.currentTimeMillis();
            for(int i=0; i<dirs.length; i++)
                checker.check(dirs[i], recursive);
            long endTime = System.currentTimeMillis();        int totalCount = 0;
            for(int i=0; i<dirs.length; i++)
            {
                int count = checker.getFileCount(dirs[i]);
                totalCount += count;
                System.out.println(dirs[i] + "下的文件数:" + count);
            }
            System.out.println("总文件数:" + totalCount);
            System.out.println("不重复的文件数:" + checker.getDistinctCount());        System.out.println("耗时:" + (endTime - startTime));
        }
    }运行结果:C:\WINNT下的文件数:8724
    D:\temp下的文件数:1422
    D:\share下的文件数:3436
    总文件数:13582
    不重复的文件数:10368
    耗时:3054修改方法createCheckKey()或类CheckKey即可实现不同的比较策略
      

  17.   

    这是JDK1.3.1_01中String的equals方法的源代码:    public boolean equals(Object anObject) {
        if (this == anObject) {
            return true;
        }
        if (anObject instanceof String) {
            String anotherString = (String)anObject;
            int n = count;
            if (n == anotherString.count) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = offset;
            int j = anotherString.offset;
            while (n-- != 0) {
                if (v1[i++] != v2[j++]) {
                return false;
                }
            }
            return true;
            }
        }
        return false;
        }楼主觉得还能优化?
    问题的关键在于减少比较次数,建议楼主找一本算法方面的书,看一下排序算法和二分查找算法。
      

  18.   

    谢谢各位了!!!
    根据 cbhyk 的提示,我找到了快速的算法!!就是:一边添加文件列表,一边比较和排序,这样列表里的文件就是排序好了的
    查找起来就快多了!!!现在结帖,发分!!!
     cbhyk 就请到另一个帖子,单独领分!!!!!1如果大家有空,帮我看看我的另一个帖子!!
    http://expert.csdn.net/Expert/TopicView1.asp?id=2929280
    谢谢!!
      

  19.   

    实在是不好意思,误导大家!
    我老是想,java的字符串比较速度怎么可能比C/C++还快呢,String的equals方法是下面这个样子的:
        public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String)anObject;
        int n = count;
        if (n == anotherString.count) {
    char v1[] = value;
    char v2[] = anotherString.value;
    int i = offset;
    int j = anotherString.offset;
    while (n-- != 0) {
        if (v1[i++] != v2[j++])
    return false;
    }
    return true;
        }
    }
    return false;
        }里面有个instanceof操作,有个类型转换,而且数组的访问是有运行期越界检查的,怎么可能比C/C++快嘛!
    定睛一看,有这么个判断:
        int n = count;
        if (n == anotherString.count) {
    因为java String的长度是构造String时就已经计算好的,那么,不同长度的String肯定不相等,根本不需要比较(在求String的长度和比较不等长String时java和Pascal相似,比C高效),而我上面给的两个String恰恰不等长!所以说速度很快,比VC编译的同样的C程序还快。但是,当把第一个String改为和第二个一样长,末尾为“1”后,整个执行时间变成了10多分钟,效率不到C的10分之一!