简体   繁体   English

Java创建新集太慢

[英]Java creation of new set too slow

I have this program where it have some recursive function similar to this: 我在这个程序中有一些类似于此的递归函数:

public static void lambda(HashSet<Integer> s){
    if(end(s)){
        return;
    }
    for(int i=0;i<w;i++){
        HashSet<Integer> p = (HashSet) s.clone();
        p.addAll(get_next_set());
        do_stuff_to(p);
        lambda(p);
    }
}

What I'm doing is union every set with the set s. 我正在做的是将每个集合与集合s合并。 And run lambda on each one of the union. 并在每个联盟上运行lambda。 I run a profiler and found the c.clone() operation took 100% of the time of my code. 我运行了探查器,发现c.clone()操作花费了我100%的代码时间。 Are there any way to speed this up considerably? 有什么办法可以大大加快速度吗?

When you are cloning, what are you really trying to do, maybe you don't need to do a complete cloan? 克隆时,您真正要做什么,也许您不需要完全克隆。

Your best bet at improving the performance of your lambda function is to extend HashSet and overide the clone definition with a custom one that is particular to your situation... 改善lambda函数性能的最佳选择是扩展HashSet并使用特定于您的情况的自定义项覆盖克隆定义...

I don't know of anyother way to really help with out more information unfortunatly. 我不知道有什么其他方法可以真正帮助您获得更多信息。

If I get it right you try to do the following: 如果我做对了,您可以尝试执行以下操作:

lambda(Set p) {
    lambda(p + further elements);
}

You can avoid cloning p eg by reimplementing a list and using the Nodes as parameters for lambda: 您可以避免克隆p,例如通过重新实现列表并将Nodes作为lambda的参数:

class Node {
    int content;
    Node next;

    Node(int content, Node next) {
        this.content = content;
        this.next = next;
    }
}

void lambda(Node set) {
    // add new elements to front
    Node newSet = set;

    for(Integer i : new_elements() ) {
        newSet = new Node(i, newSet);
    }

    lambda(newSet);
    // Observe that set is not modified by adding new elements
}

This is a low-level-solution and you would have to implement a slow sequential search/find-algorithm (if you rely on unique elements in the set), yet in my experience such a stack is a good solution for most recursive algorithms. 这是一个低级解决方案,您将必须实现缓慢的顺序搜索/查找算法(如果您依赖于集合中的唯一元素),但是以我的经验,这样的堆栈对于大多数递归算法而言都是不错的解决方案。

This is what I did to speed up everything, this way I never have to create new sets. 这是我加快所有工作的方法,因此不必创建新的集合。

public static void lambda(HashSet<Integer> s){
    if(end(s)){
        return;
    }
    ArrayList<Integer> diff = new ArrayList<Integer>();
    for(int i=0;i<w;i++){
        //an array version of the next set, it is pre-computed
        int[] a = get_next_set_array();
        for(int j=0;j<a.length;j++){
            if(!s.contains(a[j])){
               diff.add(a[j]);
            }
        }
        s.addAll(diff);
        do_stuff_to(s);
        s.removeAll(diff);
        diff.clear();
        lambda(p);
    }
}

On average this is much faster, and the program spend roughly the same amount of time on the addAll and removeAll. 平均而言,这要快得多,并且程序在addAll和removeAll上花费的时间大致相同。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM