0

标题可能不是最好的,我为此道歉。

我有几个最终静态列表用于定义数据库值的默认值。默认值列表永远不会更改,因此在填充它们时,我使用Collections.nCopies(int,T)来获取不可变列表。这些列表然后用于使用默认值填充另一个类中的列表。这些列表中的值预计会发生变化。

默认类的伪代码:

public final class FooDefaults {
    public final static List<Integer> LIST_ONE;
    public final static List<String> LIST_TWO;
    //This map allows easier access to "column" values.
    public final static List<Map<String,String>> LIST_THREE;

    static {
        LIST_ONE = Collections.nCopies(7, 5);
        LIST_TWO = Collections.nCopies(10, "boo");
        Map<String, String> temp = new java.util.LinkedHashMap<>();
        for(int i=0;i<15;i++) {
            temp.put(("Param"+i),"foo");
        }
        LIST_THREE = Collections.nCopies(10, temp);
    }
}

可编辑值类的伪代码:

public class Foo {
    //Keep the reference from changing.
    //Prevents an accidental new.
    private final List<Integer> listOne;
    private final List<String> listTwo;
    private final List<Map<String,String>> listThree;

    public Foo() {
        listOne = new java.util.ArrayList<>(FooDefaults.listOne);
        listTwo = new java.util.ArrayList<>(FooDefaults.listTwo);
        listThree = new java.util.ArrayList<>(FooDefaults.listThree);
    }
}

我担心的是,当我对这些列表执行了浅拷贝时,Foo 中列表的更改将在 FooDefaults 中的列表中可见。

这篇文章:https : //stackoverflow.com/a/1685158/1391956 建议由于字符串和整数是不可变的,我不必担心意外覆盖 FooDefaults.LIST_ONE 和 FooDefaults.LIST_TWO 中的值。

因此,我主要关心的是 FooDefaults.LIST_THREE 中的映射中包含的值。如果我在 Foo 的 listThree 中更改地图中的值,更改是否会在 FooDefaults 中可见?

如果是这样,处理这个问题的最有效方法是什么?类 Foo 可能会被实例化超过一千次并添加到另一个类的 List 中,因此速度可能会成为一个问题。

为了速度,我最初在 FooDefaults 中创建了最终的静态列表,因为我(可能不正确)假设在 FooDefaults 中创建这些列表并简单地复制数据会比每次实例化 Foo 时创建它们要快。

编辑:如果我必须执行深层复制,我计划使用类似于:

public static final List<Map<String, String>> getListThreeCopy() {
    Map<String,String> temp = new java.util.LinkedHashMap<>();
    for(Map.Entry<String, String> entry: LIST_THREE.get(0).entrySet()) {
        temp.put(entry.getKey(),entry.getValue());
    }

    List<Map<String,String>> rtnList = new java.util.ArrayList<>();
    for(int i=0;i<LIST_THREE.size();i++) {
        rtnList.add(temp);
    }
    return rtnList;
}

会有更快的方法吗?

4

1 回答 1

0

最后,我使用我帖子末尾提到的代码循环执行了 1,500 次 Deep Copy 并对其进行了计时。我对实例化代码做了同样的事情。

正如我所预料的那样,从头开始重新创建列表比深拷贝要快得多。

深度复制为 16 毫秒,而实例化为 0 毫秒。我使用 System.currentTimeMillis() 对其进行计时。

只要我只在静态函数中创建它,我就没有理由担心错误。

于 2012-10-25T23:23:02.993 回答