2

I am basically just trying to make a deep copy of ones and zeroes, so I could have used booleans, but I was wondering how to do this in genereal for integers.

private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> a) {
    ArrayList<Integer> newA = new ArrayList<>(a.size());
    for (int i = 0; i < a.size(); i++) {
        int newInt = 0;
        if (a.get(i) == 1) {
            newInt = 1;
        }
        newA.add(newInt);
    }
    return newA;
}
magicLavaLamps
  • 41
  • 1
  • 1
  • 3

4 Answers4

3

The clone() method is protected by the Integer class, so you cannot call Integer.clone() outside of that class. What you can do instead is create a new Integer.

private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> old){
    ArrayList<Integer> copy = new ArrayList<Integer>(old.size());
    for(Integer i : old){
        copy.add(new Integer(i));
    }
    return copy;
}

You can test that this works by doing something like:

public static void main (String[] args) throws java.lang.Exception
{
    ArrayList<Integer> arr = new ArrayList<>();
    for(int i = 0; i<5; i++){
        arr.add(new Integer(i));
    }
    ArrayList<Integer> x = makeDeepCopyInteger(arr);
    for(int i = 0; i<x.size(); i++){
        if(arr.get(i) == x.get(i)){
            System.out.println("Same object");
        } else {
            System.out.println("Not the same object");
        }
    }
}

Tests

Integer a = new Integer(1);
Integer b = new Integer(a);

System.out.println(a==b); // true
System.out.println(System.identityHashCode(a) == (System.identityHashCode(b))); // false;


Integer a = new Integer(1);
Integer b = a;

System.out.println(a==b); // true
System.out.println(System.identityHashCode(a) == (System.identityHashCode(b))); // true

So from my testing it seems that to create a new reference for copying to a new array, you should use new Integer(). Integer is an immutable object but that reference changes when the value of Integer changes.

Community
  • 1
  • 1
px06
  • 2,256
  • 1
  • 27
  • 47
  • 4
    Since `Integer` is immutable, you don't *need* to create a copy of it. – Kayaman Feb 06 '17 at 12:15
  • @Kayaman I did some testing on this, see my edit. Maybe I'm confused but by not creating a copy it seems to keep the old reference. – px06 Feb 06 '17 at 12:22
  • There's nothing wrong with that. Since the value of `Integer` can't change, it doesn't matter if you have 1000 lists all referring to the same `17` for example. Your last paragraph is erroneous. Since `Integer` is immutable, its value cannot change. – Kayaman Feb 06 '17 at 12:32
1

Use streams to copy objects. Easy to read, good for JIT. Following code provides a copy of a list with Integer object copies inside.

private ArrayList<Integer> makeDeepCopyInteger(ArrayList<Integer> a){
    return a.stream().map(val -> new Integer(val)).collect(toList());
}

To copy custom objects other than Integer override implement and call clone()

return a.stream().map(MyObjectClass::clone).collect(toList());

Instead of clone you can use serialization to json. E.g. as used in BeanUtils.getCopy(sourceBean) in following java-utils

Azee
  • 1,809
  • 17
  • 23
  • 1
    Welcome to stack overflow :-) Please look at [answer]. You should provide some information why your code solves the problem. Code-only answers aren't useful for the community. – JimHawkins Feb 06 '17 at 15:43
0

you'll have to iterate over the items of the list and clone them before, adding them to the new list, as mentioned here:

How to clone ArrayList and also clone its contents?

StegSchreck
  • 320
  • 4
  • 18
0

You could do something like:

public static List<Integer> clone(List<Integer> source) {
   return source.stream()
       .map( intObj -> new Integer(intObj.intValue()))
       .collect(Collectors.toList());
}

Or, more old-fashioned:

public static List<Integer> clone(List<Integer> source) {
   List<Integer> newList = new ArrayList<>();
   for(Integer intObj : source) {
      newList.add(new Integer(intObj.intValue()));
   }
   return newList;
}

Both of these could be made shorter by taking advantage of auto-boxing / auto-unboxing. But I've made it explicit to make it absolutely clear what's going on.

However, it's a pointless exercise - in fact it's actively wasteful of memory and detrimental to performance. Integer is immutable, so it's better for references to point at the same instance of Integer. Because it's not possible for the Integer to change value, it's impossible to cause any harm by sharing an instance.

This holds true for immutable objects in general, and is the reason they are a good thing.

You are very unlikely, as a beginner, to find a case in which new Integer(...) is a good idea (or even Integer.valueOf(int i), although this one might return a cached instance). If you already have an Integer, use the one you have:

 Integer oldVar = ... ;
 Integer newVar = oldVar;

Immutability means that will always be OK. It is impossible for an operation on newVar to corrupt oldVar because there is no newVar.setValue(newValue).

If you have an int use it directly and allow Java's auto-boxing to convert it into an Integer:

 int oldValue = ... ;
 Integer newValue = oldValue ; // Java will automatically put this through
                               // Integer.valueOf(int i)

You mentioned that you really wanted to work with booleans. You should consider using BitSet.

slim
  • 40,215
  • 13
  • 94
  • 127