0

The title is probably not the best, I apologize for that.

I have several final static Lists I am using to define defaults for database values. The default list of values should never change, as such when populating them, I use Collections.nCopies(int,T) to obtain an immutable List. These Lists are then used to populate lists in another class with defaults. The values in these Lists are expected to change.

Pseudocode for the class of defaults:

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);
    }
}

Pseudocode for the class of editable values:

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);
    }
}

My concern is that as I have performed a shallow copy on these lists, changes in the lists in Foo, will be visible in the Lists in FooDefaults.

This post: https://stackoverflow.com/a/1685158/1391956 suggests that due to Strings and Integers being immutable, I need not worry about accidentally overwriting the values in FooDefaults.LIST_ONE and FooDefaults.LIST_TWO.

Thus, my primary concern are the values contained within the maps in FooDefaults.LIST_THREE. If I change the values in the maps in Foo's listThree, will the change be visible in FooDefaults?

If so, what would be the most efficient way to handle this? Class Foo is likely to be instantiated over a thousand times and added to a List in another class, thus speed will potentially be an issue.

I originally created the final static lists in FooDefaults in the interest of speed, as it is my (probably incorrect) assumption that creating those Lists in FooDefaults and simply copying the data would be faster than creating them every time Foo is instantiated.

EDIT: If I must perform a Deep Copy I plan on using something similar to:

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;
}

Would there be a faster way?

Community
  • 1
  • 1
Legowaffles
  • 247
  • 2
  • 8
  • For deep copies of a list and its content, see [this](http://mre-anotherprogrammersblog.blogspot.com/2012/07/java-deep-copy-of-list-deep-copy-of.html) decent blog post. – user1329572 Oct 14 '12 at 17:00
  • @user1329572 is a Deep Copy the only way to prevent changes to the values in map contained in the FooDefaults LIST_THREE List? It is my assumption that that would be slow over thousands of values. – Legowaffles Oct 14 '12 at 17:26
  • why would you ever have thousands of objects at run-time? – user1329572 Oct 14 '12 at 19:50
  • Ack, typo, meant over a thousand. In truth, of the programs I'm making at the moment, only one should have that many, but I plan on attempting to make them on another thread. I need to be able to compare them to data contained in another class at certain points during runtime. Keeping them in memory, is perhaps not necessary. Originally those objects were stored in a List of Lists with ID to Name pairs. Making actual objects to handle the full data seemed better somehow, as I could compare it on the fly during runtime as needed. – Legowaffles Oct 14 '12 at 20:16
  • The data should not actually be needed at start up. Thus, I plan on waiting till all the data elsewhere is made, then attempt to start up a new thread to handle evaluation of the data. – Legowaffles Oct 14 '12 at 20:20

1 Answers1

0

In the end, I used the code mentioned at the end of my post in a loop to perform a Deep Copy 1,500 times and timed it. I did the same with the instantiation code.

As I somewhat expected, recreating the List from scratch is much faster than a deep copy.

16 milliseconds with the Deep Copy versus 0 milliseconds with instantiation. I timed it using System.currentTimeMillis().

So long as I only create it in a static function, I have little reason to worry about errors.

Legowaffles
  • 247
  • 2
  • 8